private bool ParseTypeOfExpression(ref ASTNode retn) { if (tokenStream.Current != ExpressionTokenType.TypeOf || tokenStream.Next != ExpressionTokenType.ParenOpen) { return(false); } tokenStream.Advance(); int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose); if (advance == -1) { Abort(); return(false); } tokenStream.Save(); ExpressionParser subParser = CreateSubParser(advance); TypeLookup typeLookup = new TypeLookup(); bool valid = subParser.ParseTypePath(ref typeLookup); subParser.Release(); if (!valid) { Abort(); // hard fail since typeof token has no other paths to go tokenStream.Restore(); return(false); } retn = ASTNode.TypeOfNode(typeLookup); return(true); }
public static bool TryParseTypeName(string typeName, out TypeLookup typeLookup) { StructList <ExpressionToken> list = StructList <ExpressionToken> .Get(); ExpressionTokenizer.Tokenize(typeName, list); ExpressionParser parser = new ExpressionParser(new TokenStream(list)); typeLookup = default; bool valid = parser.ParseTypePath(ref typeLookup); parser.Release(); list.Release(); return(valid); }
// (int)something private bool ParseDirectCastExpression(ref ASTNode retn) { if (tokenStream.Current != ExpressionTokenType.ParenOpen) { return(false); } ASTNode expression = null; int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose); if (advance == -1) { Abort(); return(false); } tokenStream.Save(); ExpressionParser subParser = CreateSubParser(advance); TypeLookup typeLookup = new TypeLookup(); bool valid = subParser.ParseTypePath(ref typeLookup); subParser.Release(); if (!valid) { tokenStream.Restore(); return(false); } if (!ParseExpression(ref expression)) { typeLookup.Release(); tokenStream.Restore(); tokenStream.Restore(); return(false); } retn = ASTNode.DirectCastNode(typeLookup, expression); return(true); }
private bool ParseAttribute(ref AttributeNode node) { if (tokenStream.Current != ExpressionTokenType.ArrayAccessOpen) { return(false); } tokenStream.Save(); tokenStream.Advance(); TypeLookup typeLookup = default; ExpressionParser parser = new ExpressionParser(tokenStream); if (!parser.ParseTypePath(ref typeLookup)) { goto fail; } tokenStream.Set(parser.GetTokenPosition()); parser.Release(false); if (tokenStream.Current == ExpressionTokenType.ArrayAccessClose) { tokenStream.Advance(); node = new AttributeNode() { typeLookup = typeLookup }; return(true); } fail: { typeLookup.Release(); parser.Release(false); return(false); } }
private bool ParseDeclaration(ref ASTNode node) { AttributeNode attrNode = null; LightList <AttributeNode> attributes = LightList <AttributeNode> .Get(); while (ParseAttribute(ref attrNode)) { attributes.Add(attrNode); if (tokenStream.Current != ExpressionTokenType.ArrayAccessOpen) { break; } } if (attributes.size == 0) { LightList <AttributeNode> .Release(ref attributes); } if (tokenStream.Current != ExpressionTokenType.Identifier) { return(false); } // modifiers? -> returnType -> name -> signature -> openBrace * closeBrace tokenStream.Save(); bool isStatic = false; if (tokenStream.Current == "static") { isStatic = true; tokenStream.Advance(); } ExpressionParser parser = new ExpressionParser(tokenStream); StructList <LambdaArgument> signature = null; TypeLookup typeLookup = default; if (!parser.ParseTypePath(ref typeLookup)) { goto fail; } tokenStream.Set(parser.GetTokenPosition()); parser.Release(false); if (tokenStream.Current != ExpressionTokenType.Identifier) { goto fail; } string name = tokenStream.Current.value; tokenStream.Advance(); // if semi colon then we have a field! if (tokenStream.Current == ExpressionTokenType.SemiColon) { tokenStream.Advance(); node = new FieldNode() { name = name, isStatic = isStatic, attributes = attributes, typeLookup = typeLookup }; return(true); } if (tokenStream.Current != ExpressionTokenType.ParenOpen) { goto fail; } signature = StructList <LambdaArgument> .Get(); if (tokenStream.NextTokenIs(ExpressionTokenType.ParenClose)) { tokenStream.Advance(2); } else { int matchingIndex = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose); if (matchingIndex == -1) { goto fail; } TokenStream subStream = tokenStream.AdvanceAndReturnSubStream(matchingIndex); subStream.Advance(); tokenStream.Advance(); if (!ExpressionParser.ParseSignature(subStream, signature)) { goto fail; } for (int i = 0; i < signature.size; i++) { if (signature.array[i].type == null) { throw new ParseException($"When defining a method you must specify a type for all arguments. Found identifier {signature.array[i].identifier} but no type was given."); } } } if (tokenStream.Current != ExpressionTokenType.ExpressionOpen) { goto fail; } BlockNode block = ParseBlock(); node = new MethodNode() { body = block, returnTypeLookup = typeLookup, attributes = attributes, name = name, isStatic = isStatic, signatureList = signature != null?signature.ToArray() : s_EmptySignature }; StructList <LambdaArgument> .Release(ref signature); parser.Release(false); return(true); fail: { tokenStream.Restore(); parser.Release(false); typeLookup.Release(); signature?.Release(); return(false); } }
private bool ParseLocalVariableDeclaration(ref ASTNode node) { ExpressionParser parser = default; TypeLookup typeLookup = default; if (tokenStream.Current == ExpressionTokenType.Var) { if (!tokenStream.NextTokenIs(ExpressionTokenType.Identifier)) { return(false); } tokenStream.Advance(); } else if (tokenStream.Current == ExpressionTokenType.Identifier) { tokenStream.Save(); parser = new ExpressionParser(tokenStream); if (!parser.ParseTypePath(ref typeLookup)) { goto fail; } tokenStream.Set(parser.GetTokenPosition()); parser.Release(false); } else { goto fail; } if (tokenStream.Current != ExpressionTokenType.Identifier) { goto fail; } string name = tokenStream.Current.value; tokenStream.Advance(); if (tokenStream.Current == ExpressionTokenType.SemiColon) { tokenStream.Advance(); node = new LocalVariableNode() { name = name, typeLookup = typeLookup // will be default for var }; return(true); } if (tokenStream.Current == ExpressionTokenType.Assign) { // todo -- would fail on this: var x = new F(() => { return x; }); tokenStream.Advance(); ASTNode expression = null; if (!ParseTerminatedExpression(ref expression)) { goto fail; } node = new LocalVariableNode() { name = name, value = expression, typeLookup = typeLookup // will be default for var }; return(true); } fail: { parser.Release(false); typeLookup.Release(); tokenStream.Restore(); return(false); } }