public static ProcessResult <Formula> ParseFormula(string formula) { var lexer = new Lexer(formula); var(success, tokens, errorMessage) = lexer.GetTokens(); if (!success) { return(new ProcessResult <Formula>(errorMessage)); } (success, errorMessage) = AreTokensValid(tokens); if (!success) { return(new ProcessResult <Formula>($"Parsing of formula ${formula} was aborted: {errorMessage}")); } TreeToken syntaxTree; (success, syntaxTree, errorMessage) = CreateSyntaxTree(tokens); if (!success) { return(new ProcessResult <Formula>(errorMessage)); } // remaining steps: // convert any nested statements to inline clips - might involve some refactoring where parsing to commands and applying these can be done selectively and not as part of the fixed pipeline we have now Token[] commandTokens; (success, commandTokens, errorMessage) = ResolveAndFlattenSyntaxTree(syntaxTree); if (!success) { return(new ProcessResult <Formula>(errorMessage)); } try { var allReferencedClips = commandTokens.Where(x => x.IsClipReference) .Select(x => ClipReference.FromString(x.Value)).ToList(); var sourceClipReferences = commandTokens.TakeWhile(x => x.IsClipReference).Select(x => ClipReference.FromString(x.Value)).ToList(); var commandTokensLists = ExtractCommandTokensLists(commandTokens.Skip(sourceClipReferences.Count).ToArray()); var commands = commandTokensLists.Select(ParseTokensToCommand).ToList(); var parsedFormula = new Formula(commands, sourceClipReferences, allReferencedClips, new Dictionary <ClipReference, ClipSlot>()); return(new ProcessResult <Formula>(parsedFormula)); } catch (ArgumentException ae) { return(new ProcessResult <Formula>($"ParseFormula threw exception: {ae.Message}")); } }
public void TestEvaluationOfClipIsAbortedWhenContentsUnchanged() { var commandHandler = new CommandHandler(); var result = commandHandler.SetAndEvaluateClipData(new Clip(4, true) { ClipReference = ClipReference.FromString("A1"), Notes = new SortedList <NoteEvent> { new NoteEvent(36, 0, .5m, 100), new NoteEvent(38, 1, .5m, 100), new NoteEvent(40, 2, .75m, 100) } }); Assert.IsTrue(result.RanToCompletion); result = commandHandler.SetAndEvaluateClipData(new Clip(4, true) { ClipReference = ClipReference.FromString("A1"), Notes = new SortedList <NoteEvent> { new NoteEvent(36, 0, .75m, 100), new NoteEvent(38, 1, .5m, 100), new NoteEvent(40, 2, .5m, 100) } }); Assert.IsTrue(result.RanToCompletion); result = commandHandler.SetAndEvaluateClipData(new Clip(4, true) { ClipReference = ClipReference.FromString("A1"), Notes = new SortedList <NoteEvent> { new NoteEvent(36, 0, .75m, 100), new NoteEvent(38, 1, .5m, 100), new NoteEvent(40, 2, .5m, 100) } }); Assert.IsFalse(result.RanToCompletion); Assert.AreEqual($"Aborted evaluation of clip at A1 since it was unchanged.", result.Warnings.FirstOrDefault()); }