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); } }