private BlockNode ParseBlock() { BlockNode retn = new BlockNode(); int expressionMatch = tokenStream.FindMatchingIndexNoAdvance(ExpressionTokenType.ExpressionOpen, ExpressionTokenType.ExpressionClose); if (expressionMatch == -1) { retn.Release(); return(null); } tokenStream.Save(); tokenStream.Advance(); while (tokenStream.CurrentIndex != expressionMatch) { ASTNode statement = null; int current = tokenStream.CurrentIndex; if (!ParseStatement(ref statement)) { retn.Release(); tokenStream.Restore(); return(null); } if (current == tokenStream.CurrentIndex) { throw new ParseException("fail recurse"); } retn.statements.Add(statement); } tokenStream.Advance(); return(retn); }
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 ParseIfStatement(ref ASTNode node) { if (tokenStream.Current != ExpressionTokenType.If) { return(false); } LightList <ElseIfNode> statements = LightList <ElseIfNode> .Get(); tokenStream.Advance(); ASTNode condition = null; if (!ParseParenExpression(ref condition)) { throw new ParseException("Expected a condition statement wrapped in parentheses but failed."); } BlockNode thenBlock = ParseBlock(); if (thenBlock == null) { throw new ParseException("Expected a block statement following an if statement but failed to parse the block"); } if (tokenStream.Current != ExpressionTokenType.ElseIf && tokenStream.Current != ExpressionTokenType.Else) { node = new IfStatementNode() { // elseIfStatements = statements.ToArray(), condition = condition, thenBlock = thenBlock }; return(true); } while (tokenStream.Current == ExpressionTokenType.ElseIf) { tokenStream.Advance(); ASTNode elseIfCondition = null; if (!ParseParenExpression(ref elseIfCondition)) { throw new ParseException("Expected a condition statement wrapped in parentheses but failed."); } BlockNode block = ParseBlock(); if (block == null) { throw new ParseException("Expected a block statement following an if statement but failed to parse the block"); } statements.Add(new ElseIfNode() { condition = elseIfCondition, thenBlock = block }); } BlockNode elseBlock = null; if (tokenStream.Current == ExpressionTokenType.Else) { tokenStream.Advance(); elseBlock = ParseBlock(); if (elseBlock == null) { throw new ParseException("Expected a block statement following an else statement but failed to parse the block"); } } node = new IfStatementNode() { condition = condition, thenBlock = thenBlock, elseIfStatements = statements.size == 0 ? null : statements.ToArray(), elseBlock = elseBlock }; statements.Release(); return(true); }