public void ResolveCodeOrState(StatesInfo statesInfo) { if (codeOrStateResolved) { return; } string code_str = code.AsString().Trim().Replace(" ", ""); if (PopState == code_str) { targetState = PopState; code = null; } else { string state = statesInfo.StateNames.SingleOrDefault(it => pushState + it == code_str); if (state != null) { targetState = state; code = null; } } codeOrStateResolved = true; }
public CodeBody TryParseBodyOrStatement(bool allowEmpty = false) { Func <ASTNode> bodyParser = () => { CodeBody body = null; var single = TryParseInnerStatement(); if (single != null) { var content = new List <Statement>(); content.Add(single); body = new CodeBody(content, single.StartPos, single.EndPos); } else { body = TryParseBody(); } if (body == null) { if (allowEmpty && Tokens.ConsumeToken(TokenType.SemiColon) != null) { body = new CodeBody(null, CurrentPosition.GetModifiedPosition(0, -1, -1), CurrentPosition); } else { return(Error("Expected a code body or single statement!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } } return(body); }; return((CodeBody)Tokens.TryGetTree(bodyParser)); }
public bool VisitNode(CodeBody node) { foreach (Statement statement in node.Statements) { Emit(statement); } return(true); }
public FactoryTypeInfo(string name, string parent, bool withOverride) { this.ClassName = name; this.Parent = parent; this.WithOverride = withOverride; this.Code = new CodeBody(); this.Params = new CodeBody(); }
public bool VisitNode(CodeBody node) { foreach (Statement s in node.Statements) //TODO: make this proper { s.AcceptVisitor(this); } return(true); }
private static AltRule createSubstitution(SymbolPosition position, string substSymbolName) { var code = new CodeBody().AddIdentifier("obj"); return(AltRule.CreateInternally(position, new RhsGroup[] { RhsGroup.CreateSequence(position, RepetitionEnum.Once, new RhsSymbol(position, "obj", substSymbolName)) }, new CodeMix(CodeMix.SubstitutionComment).AddBody(code))); }
/// <summary> /// Debugging routine to dump the code to a given file. Can be called directly from within /// the debugger. /// </summary> /// <param name="output"></param> internal void DumpToFile(System.IO.FileInfo output) { using (var writer = output.CreateText()) { foreach (var l in CodeBody.CodeItUp()) { writer.WriteLine(l); } } }
public bool VisitNode(CodeBody node) { foreach (Statement s in node.Statements) //TODO: make this proper { if (s.AcceptVisitor(this) && !StringParserBase.SemiColonExceptions.Contains(s.Type)) { Append(";"); } } return(true); }
private LexItem(IEnumerable <ILexPattern> patterns, IEnumerable <string> contextTokens, string token, string state, bool isExpression, CodeBody code, bool resolved) { this.states = new HashSet <string>(); this.InputPatterns = patterns.ToArray(); this.Context = contextTokens.ToArray(); this.TerminalName = token; this.targetState = state; this.code = code; this.IsExpression = isExpression; this.codeOrStateResolved = (resolved || this.targetState != null || this.code == null); }
public IfStatement TryParseIf() { Func <ASTNode> ifParser = () => { var token = Tokens.ConsumeToken(TokenType.If); if (token == null) { return(null); } if (Tokens.ConsumeToken(TokenType.LeftParenth) == null) { return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var condition = TryParseExpression(); if (condition == null) { return(Error("Expected an expression as the if-condition!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } if (condition.ResolveType().Name != "bool") // TODO: check/fix! { return(Error("Expected a boolean result from the condition!", condition.StartPos, condition.EndPos)); } if (Tokens.ConsumeToken(TokenType.RightParenth) == null) { return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } CodeBody thenBody = TryParseBodyOrStatement(); if (thenBody == null) { return(Error("Expected a statement or code block!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } CodeBody elseBody = null; var elsetoken = Tokens.ConsumeToken(TokenType.Else); if (elsetoken != null) { elseBody = TryParseBodyOrStatement(); if (elseBody == null) { return(Error("Expected a statement or code block!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } } return(new IfStatement(condition, thenBody, token.StartPosition, token.EndPosition, elseBody)); }; return((IfStatement)Tokens.TryGetTree(ifParser)); }
public DoUntilLoop TryParseDoUntil() { Func <ASTNode> untilParser = () => { var doToken = Tokens.ConsumeToken(TokenType.Do); if (doToken == null) { return(null); } _loopCount++; CodeBody body = TryParseBodyOrStatement(); _loopCount--; if (body == null) { return(null); } var untilToken = Tokens.ConsumeToken(TokenType.Until); if (untilToken == null) { return(Error("Expected 'until'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } if (Tokens.ConsumeToken(TokenType.LeftParenth) == null) { return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var condition = TryParseExpression(); if (condition == null) { return(Error("Expected an expression as the until condition!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } if (condition.ResolveType().Name != "bool") // TODO: check/fix! { return(Error("Expected a boolean result from the condition!", condition.StartPos, condition.EndPos)); } if (Tokens.ConsumeToken(TokenType.RightParenth) == null) { return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } return(new DoUntilLoop(condition, body, untilToken.StartPosition, untilToken.EndPosition)); }; return((DoUntilLoop)Tokens.TryGetTree(untilParser)); }
private static AltRule createAppend(SymbolPosition position, string lhsSymbolName, IEnumerable <string> elementTypeNames, params RhsSymbol[] symbols) { // if it does not exists it means we don't care about adding it IEnumerable <RhsSymbol> named_symbols = symbols.Where(it => it.ObjName != null).ToArray(); string list_obj_name; if (named_symbols.Count() == 1) { list_obj_name = "list"; } else { list_obj_name = "tuple_list"; } // since we are creating this code, the only conflict can come from symbol object names list_obj_name = Grammar.RegisterName(list_obj_name, named_symbols.Select(it => it.ObjName).ToList()); var code = new CodeBody().AddSnippet("{"); if (named_symbols.Count() == 1) { code.AddWithIdentifier(list_obj_name, ".", "Add", "(", named_symbols.Single().ObjName, ");"); } else { foreach (Tuple <RhsSymbol, int> sym_pair in named_symbols.ZipWithIndex()) { code.AddWithIdentifier(list_obj_name, ".", CodeWords.Item(sym_pair.Item2 + 1), ".", "Add", "("); code.AddIdentifier(sym_pair.Item1.ObjName); code.AddSnippet(");"); } } code.AddWithIdentifier("return", " ", list_obj_name, ";}"); return(AltRule.CreateInternally(position, new RhsGroup[] { RhsGroup.CreateSequence(position, RepetitionEnum.Once, new RhsSymbol(position, list_obj_name, lhsSymbolName)), RhsGroup.CreateSequence(position, RepetitionEnum.Once, symbols.Select(it => it.ShallowClone().SetSkip(false)).ToArray()) }, new CodeMix(CodeMix.AppendComment).AddBody(code))); }
public WhileLoop TryParseWhile() { Func <ASTNode> whileParser = () => { var token = Tokens.ConsumeToken(TokenType.While); if (token == null) { return(null); } if (Tokens.ConsumeToken(TokenType.LeftParenth) == null) { return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var condition = TryParseExpression(); if (condition == null) { return(Error("Expected an expression as the while condition!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } if (condition.ResolveType().Name != "bool") // TODO: check/fix! { return(Error("Expected a boolean result from the condition!", condition.StartPos, condition.EndPos)); } if (Tokens.ConsumeToken(TokenType.RightParenth) == null) { return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } _loopCount++; CodeBody body = TryParseBodyOrStatement(allowEmpty: true); _loopCount--; if (body == null) { return(null); } return(new WhileLoop(condition, body, token.StartPosition, token.EndPosition)); }; return((WhileLoop)Tokens.TryGetTree(whileParser)); }
private static CodeBody makeTupleListCode(IEnumerable <string> elementTypeNames) { if (!elementTypeNames.Any()) { throw new ArgumentException(); } if (elementTypeNames.Count() == 1) { return(makeListCode(elementTypeNames.Single())); } else { var code = new CodeBody() .AddWithIdentifier(CodeWords.Tuple, "<") .AddCommaSeparatedElements(elementTypeNames.Select(it => makeListCode(it))) .AddSnippet(">"); return(code); } }
public SwitchStatement TryParseSwitch() { Func <ASTNode> switchParser = () => { var token = Tokens.ConsumeToken(TokenType.Switch); if (token == null) { return(null); } if (Tokens.ConsumeToken(TokenType.LeftParenth) == null) { return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var expression = TryParseExpression(); if (expression == null) { return(Error("Expected an expression as the switch value!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } if (Tokens.ConsumeToken(TokenType.RightParenth) == null) { return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } _switchCount++; CodeBody body = TryParseBodyOrStatement(); _switchCount--; if (body == null) { return(Error("Expected switch code block!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } return(new SwitchStatement(expression, body, token.StartPosition, token.EndPosition)); }; return((SwitchStatement)Tokens.TryGetTree(switchParser)); }
// funcRef == null, means it is (not created because it is pointless) identity function private CodeBody createFunctionCall(CodeBody funcRef, IEnumerable <CodeBody> arguments) { if (funcRef == null && arguments.Count() != 1) { throw new ArgumentException("Identity function works only for single argument"); } var code = new CodeBody(); if (funcRef != null) { code.Append(funcRef).AddSnippet("("); } code.AddCommaSeparatedElements(arguments); if (funcRef != null) { code.AddSnippet(")"); } return(code); }
private string registerLambda(string lhsSymbol, IEnumerable <string> inputTypeNames, string outputTypeName, // each pair holds real name (like "expr") and (as backup) dummy name, like "_2" IEnumerable <Tuple <string, string> > arguments, CodeBody body) { if (inputTypeNames.Count() != arguments.Count()) { throw new ArgumentException("Creating a function -- types count vs. arguments count mismatch."); } CodeLambda lambda = null; // identity function, i.e. f(x) = x, we check only real name, if it was a dummy name, it would be if (arguments.Count() == 1) { if (arguments.Single().Item1 == body.Make().Trim()) { lambda = FunctionRegistry.IdentityFunction(lhsSymbol); } else if (arguments.Single().Item2 == body.Make().Trim()) { throw new InvalidOperationException("Somehow dummy name which should not exist was referenced."); } } if (lambda == null) { lambda = new CodeLambda(lhsSymbol, arguments.SyncZip(inputTypeNames) .Select(it => FuncParameter.Create(it.Item1.Item1, it.Item1.Item2, it.Item2)), outputTypeName, body); } return(functionsRegistry.Add(lambda)); }
public CodeBodyParser(TokenStream <String> tokens, CodeBody body, SymbolTable symbols, ASTNode containingNode, MessageLog log = null) { Log = log ?? new MessageLog(); Symbols = symbols; Tokens = tokens; _loopCount = 0; _switchCount = 0; Node = containingNode; Body = body; OuterClassScope = NodeUtils.GetOuterClassScope(containingNode); // TODO: refactor a better solution to this mess if (IsState) { NodeVariables = (containingNode as State); } else if (IsFunction) { NodeVariables = (containingNode as Function); } else if (IsOperator) { NodeVariables = (containingNode as OperatorDeclaration); } }
public bool VisitNode(CodeBody node) { throw new NotImplementedException(); }
private void DecompileLoopsAndIfs(List <Statement> statements, Dictionary <Statement, ushort> positions, bool inLoop = false) { var defaultCaseStatements = new Stack <Statement>(); var switchEnds = new Dictionary <int, ushort>(); for (int i = statements.Count - 1; i >= 0; i--) { var cur = statements[i]; if (!positions.TryGetValue(cur, out ushort curPos)) { continue; //default param values, labels } if (cur is UnconditionalJump loopEnd && loopEnd.JumpLoc < curPos) { //end of while or for loop var continueToPos = curPos; Statement statementBeforeEndOfLoop = statements[i - 1]; bool isForLoop = IsIncrementDecrement(statementBeforeEndOfLoop, out Statement update); var loopStart = StatementLocations[loopEnd.JumpLoc]; int conditionIdx = statements.IndexOf(loopStart); int skipStart = conditionIdx; int numToSkip = i - conditionIdx + 1; if (!(statements[conditionIdx] is ConditionalJump conditionalJump)) { //TODO: replace the unconditional jump with a goto? or perhaps this is a loop with no condition? throw new Exception("Invalid Control Flow!"); } CodeBody loopBody = new CodeBody(statements.GetRange(conditionIdx + 1, i - conditionIdx - 1)); if (!isForLoop && !(statementBeforeEndOfLoop is Jump)) { //check to see if there is an unconditional jump to the statement before the end of the loop. This indicates a continue inside a for loop var checkPos = positions[statementBeforeEndOfLoop]; if (loopBody.Statements.OfType <UnconditionalJump>().Any(possibleContinue => possibleContinue.JumpLoc == checkPos)) { update = statementBeforeEndOfLoop; isForLoop = true; } } else if (isForLoop) { //check to see if there is an unconditional jump to the end of the loop. //This indicates that the loop is NOT a for loop, as there is no way to skip the increment statement in a for loop for (int j = i - 2; j > conditionIdx; j--) { if (statements[j] is UnconditionalJump unj && unj.JumpLoc == curPos) { isForLoop = false; break; } } } AssignStatement forInit = null; ushort loopLoc = loopEnd.JumpLoc; if (isForLoop && conditionIdx > 0 && statements[conditionIdx - 1] is AssignStatement assignStatement) { forInit = assignStatement; skipStart = conditionIdx - 1; numToSkip++; loopLoc = positions[assignStatement]; } Statement loop; Expression condition = conditionalJump.Condition; if (isForLoop) { continueToPos = positions[statementBeforeEndOfLoop]; loopBody.Statements.RemoveAt(loopBody.Statements.Count - 1); loop = new ForLoop(forInit, condition, update, loopBody); } else { loop = new WhileLoop(condition, loopBody); } //recurse into body of loop DecompileLoopsAndIfs(loopBody.Statements, positions, true); //convert unconditional jumps into continue and break const int sizeOfUnconditionalJump = 3; ConvertJumps(loopBody, continueToPos, loopEnd.JumpLoc, curPos + sizeOfUnconditionalJump); statements.RemoveRange(skipStart, numToSkip); statements.Insert(skipStart, loop); StatementLocations[loopLoc] = loop; positions[loop] = loopLoc; i = skipStart; }
private AltRule createSeed(SymbolPosition position, List <Production> productions, bool doubled, // should we double the seed right at the start string lhsSymbolName, IEnumerable <string> elementTypeNames, params RhsSymbol[] symbols) { RhsSymbol[] init_symbols = symbols.Where(it => !it.SkipInitially).ToArray(); var main_code = new CodeBody().AddWithIdentifier(CodeWords.New, " "); main_code.Append(makeTupleListCode(position, elementTypeNames)); main_code.AddSnippet("("); IEnumerable <CodeBody> code_lists = elementTypeNames.Select(it => new CodeBody().AddWithIdentifier(CodeWords.New, " ", CodeWords.List, "<", it, ">{")).ToList(); // purpose: to handle names in doubled seed mode Dictionary <RhsSymbol, string[]> obj_name_substs = new Dictionary <RhsSymbol, string[]>(); { IEnumerable <RhsSymbol> named_symbols = symbols.Where(it => it.ObjName != null); if (named_symbols.Any()) { foreach (Tuple <RhsSymbol, CodeBody> tuple in named_symbols.SyncZip(code_lists)) { RhsSymbol nsymbol = tuple.Item1; CodeBody lcode = tuple.Item2; bool double_sym = doubled && !nsymbol.SkipInitially; string[] name_subst = new string[double_sym ? 2 : 1]; obj_name_substs.Add(nsymbol, name_subst); // if we double the element, we have to come up with new names if (double_sym) { name_subst[0] = AutoNames.Double1 + nsymbol.ObjName + "__"; name_subst[1] = AutoNames.Double2 + nsymbol.ObjName + "__"; } else { name_subst[0] = nsymbol.ObjName; } for (int i = 0; i < (double_sym ? 2 : 1); ++i) { if (i == 1) { lcode.AddSnippet(","); } if (double_sym) { lcode.AddIdentifier(name_subst[i]); } else { lcode.AddIdentifier(nsymbol.ObjName); } } } } } foreach (Tuple <CodeBody, int> code_pair in code_lists.ZipWithIndex()) { code_pair.Item1.AddSnippet("}"); if (code_pair.Item2 > 0) { main_code.AddSnippet(","); } main_code.Append(code_pair.Item1); } main_code.AddSnippet(")"); // in case of doubled seed we have to rename the symbols // otherwise just make shallow copies without renaming // but since we already set proxy name correctly, we can use shared code for both cases var seed_symbols = new LinkedList <RhsSymbol>(); for (int i = 0; i < (doubled ? 2 : 1); ++i) { foreach (RhsSymbol sym in (i == 0 ? init_symbols : symbols)) { if (sym.ObjName == null) { seed_symbols.AddLast(sym.ShallowClone()); } else { int s_idx = (i == 1 && sym.SkipInitially) ? 0 : i; seed_symbols.AddLast(sym.Renamed(obj_name_substs[sym][s_idx])); } } } return(AltRule.CreateInternally(position, // are there any symbols for production seed_symbols.Any() ? new RhsGroup[] { RhsGroup.CreateSequence(position, RepetitionEnum.Once, seed_symbols.Select(it => it.SetSkip(false)).ToArray()) } : new RhsGroup[] { }, new CodeMix(CodeMix.SeedComment).AddBody(main_code))); }
internal FactoryTypeInfo SetParams(CodeBody paramsCode) { this.Params = paramsCode; return(this); }
private ProductionInfo makeBuilderCall(string lhsSymbol, RecursiveEnum recursive, AltRule alt, IEnumerable <SymbolMarked> symbolsMarked, string treeNodeName) { // add production with no code var prod_info = new ProductionInfo(alt.Position, lhsSymbol, recursive, symbolsMarked.Where(it => it.IsEnabled).Select(it => it.Symbol), alt.MarkWith); CodeBody code_body = null; if (alt.Code != null) { code_body = (alt.Code as CodeMix).BuildBody(symbolsMarked.Where(sym => sym.Symbol.ObjName != null) .Select(sym => sym.Symbol.GetCodeArgumentNames().Select(it => Tuple.Create(it, sym.IsEnabled))).Flatten()) .Trim(); string identity_function_on = null; // are we just passing one of the parameters? if (code_body.IsIdentity) { identity_function_on = code_body.IdentityIdentifier; } foreach (string var_name in code_body.GetVariables()) { SymbolMarked sym = symbolsMarked .Where(sm => sm.Symbol.GetCodeArgumentNames().Contains(var_name)) // there could be duplicates so we "prefer" enabled element .OrderBy(it => it.IsEnabled ? 0 : 1) .FirstOrDefault(); if (sym != null) { sym.IsParamUsed = true; } } var anon_args = new Dictionary <SymbolMarked, string>(); foreach (Tuple <SymbolMarked, int> sym_pair in symbolsMarked.ZipWithIndex()) { if (sym_pair.Item1.Symbol.ObjName == null) { anon_args.Add(sym_pair.Item1, code_body.RegisterNewIdentifier("_" + sym_pair.Item2)); } } IEnumerable <SymbolMarked> arg_symbols = symbolsMarked.Where(it => it.IsEnabled || it.IsParamUsed).ToList(); // build external function to run the user code string func_ref = registerLambda(lhsSymbol, arg_symbols.Select(sym => sym.Symbol.GetCodeArgumentTypes(grammar)).Flatten(), grammar.TreeNodeName, arg_symbols.Select(sym => sym.Symbol.GetCodeArgumentNames() .Select(it => Tuple.Create(it, anon_args.GetOrNull(sym)))).Flatten(), code_body); // build a lambda with call to a just built function // note that our lambda can have fewer arguments than the actual fuction // in such case we pass "nulls" for disabled arguments // we add nulls to params in order to keep track which arguments comes from which parameters IEnumerable <FuncParameter> lambda_params = arg_symbols.Where(it => it.IsEnabled) .Select(it => FuncParameter.Create(it.Symbol.ObjName, anon_args.GetOrNull(it), grammar.GetTypeNameOfSymbol(it.Symbol))).ToArray(); // if the code indicates that this is identity function, then just find out which parameter is passed along if (identity_function_on != null) { // we can fail for two reasons here: // (1) ok -- single variable we found in the code body is not a parameter, but global variable // (2) BAD -- we have case of unpacking the data, and that case so far we cannot handle // ad.2) consider such rule as // x -> (a b)+ { b }; // "a" and "b" will be handled as tuple of lists // so in entry function we will get a tuple, and then we will call actuall user action code // some "__function_13__(a,b)" which returns the "b" // so we could compute index for inner parameter (for "b" it is 1) // but we cannot compute index for outer function, because there is no index for "b" at all // there is only one parameter -- tuple -- holding "a" (in Item1) and "b" (in Item2) at the same time // so if anything we would have to introduce some combo index: // outer index --> optional unpacking index --> inner index // too much trouble for now Option <int> index = lambda_params.Select(it => it.Name) .ZipWithIndex().Where(it => it.Item1 == identity_function_on).Select(it => it.Item2).OptSingle(); if (index.HasValue) { prod_info.IdentityOuterFunctionParamIndex = index.Value; } } prod_info.ActionCode = CodeLambda.CreateProxy( lhsSymbol, // lambda arguments lambda_params, treeNodeName, func_ref, arg_symbols.Select(arg => arg.Symbol.CombinedSymbols == null // regular symbols ? new[] { new CodeBody().AddIdentifier(arg.IsEnabled ? (arg.Symbol.ObjName ?? anon_args[arg]) : CodeWords.Null) } // compound symbols, we have to use embedded atomic symbols instead now : arg.Symbol.UnpackTuple(arg.IsEnabled) ) .Flatten()); prod_info.CodeComment = alt.Code.Comment; } return(prod_info); }
public void Update() { if (playing) { Input.mbPos = mbPosPast; Input.mbWheel = 0; if (past != null && past.frame == _frame - 1) { past.PlayPast(); past = null; } if (future == null) { if (reader.BaseStream.Position < reader.BaseStream.Length) { future = GetFuture(); Future GetFuture() { Future future = new Future(); while (true) { CodeBody code = (CodeBody)reader.ReadByte(); switch (code) { case CodeBody.Frame: future.frame = lastFrameWrittenToStream + reader.ReadInt32(); lastFrameWrittenToStream = future.frame; return(future); case CodeBody.MousePos: future.mbPos = reader.ReadVector2(); break; case CodeBody.MouseWheel: future.mbWheel = reader.ReadInt32(); break; case CodeBody.KeyPressed: future.pressed.Add(Input.keys[reader.ReadInt16()]); break; case CodeBody.KeyReleased: future.released.Add(Input.keys[reader.ReadInt16()]); break; default: throw new Exception(); } } } } else { // stop playing //if (_frame >= frames) //{ //} Input.ClearKeys(); _playing = false; Input.blockInput = false; if (FinishPlaying != null) { FinishPlaying(this, EventArgs.Empty); } return; } } if (future.frame == _frame) { future.Play(); past = future; future = null; } else if (future.frame < _frame) { throw new Exception(); } mbPosPast = Input.mbPos; } if (recording) { // update format: // 1(byte): frame distance to last input frame // frame(int) // 2(byte): mouse // x(Vector2) // 3(byte): mouseWheel // wheel(int) // 4(byte): key pressed // id(short) // 5(byte): key released // id(short) long prevStreamPos = writer.BaseStream.Position; if (mouseInput) { #region Mouse if (Input.mbPos != mbPosPast) { writer.Write((byte)CodeBody.MousePos); writer.Write(Input.mbPos); mbPosPast = Input.mbPos; } if (Input.mbWheel != 0) { writer.Write((byte)CodeBody.MouseWheel); writer.Write(Input.mbWheel); } #endregion } #region Keys for (int i = 0; i < keysInput.Length; i++) { if (keysInput[i].pressed) { writer.Write((byte)CodeBody.KeyPressed); writer.Write(keysInput[i].id); } else if (keysInput[i].released) { writer.Write((byte)CodeBody.KeyReleased); writer.Write(keysInput[i].id); } } #endregion if (prevStreamPos != writer.BaseStream.Position) { writer.Write((byte)CodeBody.Frame); writer.Write(_frame - lastFrameWrittenToStream); lastFrameWrittenToStream = _frame; writer.Flush(); } } if (recording || playing) { _frame++; } }
internal FactoryTypeInfo SetCode(CodeBody code) { this.Code = code; return(this); }
public Function TryParseFunction() { Func <ASTNode> stubParser = () => { var specs = ParseSpecifiers(GlobalLists.FunctionSpecifiers); if (Tokens.ConsumeToken(TokenType.Function) == null) { return(null); } Token <String> returnType = null, name = null; var firstString = Tokens.ConsumeToken(TokenType.Word); if (firstString == null) { return(Error("Expected function name or return type!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var secondString = Tokens.ConsumeToken(TokenType.Word); if (secondString == null) { name = firstString; } else { returnType = firstString; name = secondString; } VariableType retVarType = returnType != null ? new VariableType(returnType.Value, returnType.StartPosition, returnType.EndPosition) : null; if (Tokens.ConsumeToken(TokenType.LeftParenth) == null) { return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var parameters = new List <FunctionParameter>(); while (CurrentTokenType != TokenType.RightParenth) { var param = TryParseParameter(); if (param == null) { return(Error("Malformed parameter!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } parameters.Add(param); if (Tokens.ConsumeToken(TokenType.Comma) == null && CurrentTokenType != TokenType.RightParenth) { return(Error("Unexpected parameter content!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } } if (Tokens.ConsumeToken(TokenType.RightParenth) == null) { return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } CodeBody body = new CodeBody(null, CurrentPosition, CurrentPosition); SourcePosition bodyStart = null, bodyEnd = null; if (Tokens.ConsumeToken(TokenType.SemiColon) == null) { if (!ParseScopeSpan(TokenType.LeftBracket, TokenType.RightBracket, out bodyStart, out bodyEnd)) { return(Error("Malformed function body!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } body = new CodeBody(null, bodyStart, bodyEnd); } return(new Function(name.Value, retVarType, body, specs, parameters, name.StartPosition, name.EndPosition)); }; return((Function)Tokens.TryGetTree(stubParser)); }
internal static IEnumerable <LexItem> AsDetectedStatement(IEnumerable <ILexPattern> patterns, IEnumerable <IEnumerable <string> > contextTokens, string token, string state, CodeBody code, bool resolved = false) { // we have to build up at least one empty context, otherwise we will not produce any elements return(populateContexts(contextTokens).Select(ctx => new LexItem(patterns, ctx, token, state, !code.HasStatement, code, resolved)).ToArray()); }
public State TryParseState() { Func <ASTNode> stateSkeletonParser = () => { var specs = ParseSpecifiers(GlobalLists.StateSpecifiers); if (Tokens.ConsumeToken(TokenType.State) == null) { return(null); } var name = Tokens.ConsumeToken(TokenType.Word); if (name == null) { return(Error("Expected state name!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var parent = TryParseParent(); if (Tokens.ConsumeToken(TokenType.LeftBracket) == null) { return(Error("Expected '{'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } List <Function> ignores = new List <Function>(); if (Tokens.ConsumeToken(TokenType.Ignores) != null) { do { VariableIdentifier variable = TryParseVariable(); if (variable == null) { return(Error("Malformed ignore statement!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } ignores.Add(new Function(variable.Name, null, null, null, null, variable.StartPos, variable.EndPos)); } while (Tokens.ConsumeToken(TokenType.Comma) != null); if (Tokens.ConsumeToken(TokenType.SemiColon) == null) { return(Error("Expected semi-colon!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } } var funcs = new List <Function>(); Function func = TryParseFunction(); while (func != null) { funcs.Add(func); func = TryParseFunction(); } var bodyStart = Tokens.CurrentItem.StartPosition; while (Tokens.CurrentItem.Type != TokenType.RightBracket && !Tokens.AtEnd()) { Tokens.Advance(); } var bodyEnd = Tokens.CurrentItem.StartPosition; if (Tokens.ConsumeToken(TokenType.RightBracket) == null) { return(Error("Expected '}'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var body = new CodeBody(new List <Statement>(), bodyStart, bodyEnd); var parentState = parent != null ? new State(parent.Name, null, null, null, null, null, null, parent.StartPos, parent.EndPos) : null; return(new State(name.Value, body, specs, parentState, funcs, ignores, null, name.StartPosition, name.EndPosition)); }; return((State)Tokens.TryGetTree(stateSkeletonParser)); }
private static CodeBody makeListCode(string elementTypeName) { var code = new CodeBody().AddWithIdentifier(CodeWords.List, "<", elementTypeName, ">"); return(code); }
public OperatorDeclaration TryParseOperatorDecl() { Func <ASTNode> operatorParser = () => { var specs = ParseSpecifiers(GlobalLists.FunctionSpecifiers); var token = Tokens.ConsumeToken(TokenType.Operator) ?? Tokens.ConsumeToken(TokenType.PreOperator) ?? Tokens.ConsumeToken(TokenType.PostOperator) ?? new Token <String>(TokenType.INVALID); if (token.Type == TokenType.INVALID) { return(null); } Token <String> precedence = null; if (token.Type == TokenType.Operator) { if (Tokens.ConsumeToken(TokenType.LeftParenth) == null) { return(Error("Expected '('! (Did you forget to specify operator precedence?)", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } precedence = Tokens.ConsumeToken(TokenType.IntegerNumber); if (precedence == null) { return(Error("Expected an integer number!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } if (Tokens.ConsumeToken(TokenType.RightParenth) == null) { return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } } Token <String> returnType = null, name = null; var firstString = TryParseOperatorIdentifier(); if (firstString == null) { return(Error("Expected operator name or return type!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var secondString = TryParseOperatorIdentifier(); if (secondString == null) { name = firstString; } else { returnType = firstString; name = secondString; } VariableType retVarType = returnType != null ? new VariableType(returnType.Value, returnType.StartPosition, returnType.EndPosition) : null; if (Tokens.ConsumeToken(TokenType.LeftParenth) == null) { return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } var operands = new List <FunctionParameter>(); while (CurrentTokenType != TokenType.RightParenth) { var operand = TryParseParameter(); if (operand == null) { return(Error("Malformed operand!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } operands.Add(operand); if (Tokens.ConsumeToken(TokenType.Comma) == null && CurrentTokenType != TokenType.RightParenth) { return(Error("Unexpected operand content!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } } if (token.Type == TokenType.Operator && operands.Count != 2) { return(Error("In-fix operators requires exactly 2 parameters!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } else if (token.Type != TokenType.Operator && operands.Count != 1) { return(Error("Post/Pre-fix operators requires exactly 1 parameter!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } if (Tokens.ConsumeToken(TokenType.RightParenth) == null) { return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } CodeBody body = new CodeBody(null, CurrentPosition, CurrentPosition); SourcePosition bodyStart = null, bodyEnd = null; if (Tokens.ConsumeToken(TokenType.SemiColon) == null) { if (!ParseScopeSpan(TokenType.LeftBracket, TokenType.RightBracket, out bodyStart, out bodyEnd)) { return(Error("Malformed operator body!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1))); } body = new CodeBody(null, bodyStart, bodyEnd); } // TODO: determine if operator should be a delimiter! (should only symbol-based ones be?) if (token.Type == TokenType.PreOperator) { return(new PreOpDeclaration(name.Value, false, body, retVarType, operands.First(), specs, name.StartPosition, name.EndPosition)); } else if (token.Type == TokenType.PostOperator) { return(new PostOpDeclaration(name.Value, false, body, retVarType, operands.First(), specs, name.StartPosition, name.EndPosition)); } else { return(new InOpDeclaration(name.Value, Int32.Parse(precedence.Value), false, body, retVarType, operands.First(), operands.Last(), specs, name.StartPosition, name.EndPosition)); } }; return((OperatorDeclaration)Tokens.TryGetTree(operatorParser)); }