public static bool CheckForPreprocessorNode(Genero4glParser parser, AstNode4gl node) { PreprocessorNode preNode; if (PreprocessorNode.TryParseNode(parser, out preNode) && node != null) { // TODO: determine context of the preprocessor via containingNode if (preNode.Type == PreprocessorType.Include && !string.IsNullOrWhiteSpace(preNode.IncludeFile)) { if (node.IncludeFiles.ContainsKey(preNode.IncludeFile)) { node.IncludeFiles[preNode.IncludeFile].Add(preNode); } else { node.IncludeFiles.Add(preNode.IncludeFile, new List <PreprocessorNode>() { preNode }); } } return(true); } return(false); }
public static bool TryParseNode(Genero4glParser parser, out OtherwiseStatement node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.OtherwiseKeyword)) { result = true; node = new OtherwiseStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.DecoratorEnd = parser.Token.Span.End; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !parser.PeekToken(TokenKind.WhenKeyword) && !parser.PeekToken(TokenKind.OtherwiseKeyword) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.CaseKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExitKeywords, contextStatementFactories, expressionOptions) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; node.Children.Add(stmtNode.StartIndex, stmtNode); if (statement is ExitStatement && (statement as ExitStatement).ExitType != TokenKind.CaseKeyword) { if (validExitKeywords != null && !validExitKeywords.Contains((statement as ExitStatement).ExitType)) { parser.ReportSyntaxError("Invalid exit statement for case statement block detected."); } } } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); node.EndIndex = parser.Token.Span.End; } return(result); }
public FunctionBlockNode GetContainingFunction(int index, bool returnNextIfOutside) { AstNode4gl containingNode = null; List <int> keys = null; int searchIndex = -1; int key = -1; if (_body.Children.Count > 0) { // do a binary search to determine what node we're in keys = _body.Children.Select(x => x.Key).ToList(); searchIndex = keys.BinarySearch(index); if (searchIndex < 0) { searchIndex = ~searchIndex; if (searchIndex > 0) { searchIndex--; } } key = keys[searchIndex]; // TODO: need to handle multiple results of the same name containingNode = Body.Children[key] as AstNode4gl; if (returnNextIfOutside && containingNode != null && containingNode.EndIndex < index) { // need to go to the next function searchIndex++; if (keys.Count > searchIndex) { key = keys[searchIndex]; containingNode = Body.Children[key] as AstNode4gl; } else { containingNode = null; } } } if (containingNode != null && containingNode is FunctionBlockNode) { return(containingNode as FunctionBlockNode); } return(null); }
public Genero4glAst(AstNode4gl body, int[] lineLocations, GeneroLanguageVersion langVersion = GeneroLanguageVersion.None, IProjectEntry projEntry = null, string filename = null) : base(body, lineLocations, langVersion, projEntry, filename) { InitializeBuiltins(); InitializeImportedPackages(); // for this instance InitializePackages(); if (body is ModuleNode) { foreach (var import in (body as ModuleNode).CExtensionImports) { if (_importedPackages.ContainsKey(import)) { _importedPackages[import] = true; } } } }
public static bool TryParseNode(Genero4glParser parser, out IfBlockContentsNode node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = new IfBlockContentsNode(); node.StartIndex = parser.Token.Span.Start; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !parser.PeekToken(TokenKind.ElseKeyword) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.IfKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords)) { AstNode4gl stmtNode = statement as AstNode4gl; if (stmtNode != null && !node.Children.ContainsKey(stmtNode.StartIndex)) { node.Children.Add(stmtNode.StartIndex, stmtNode); } } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); node.EndIndex = parser.Token.Span.End; return(true); }
public static bool TryParseNode(Genero4glParser parser, out ForeachStatement node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.ForeachKeyword)) { result = true; node = new ForeachStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.InputVars = new List <FglNameExpression>(); node.OutputVars = new List <FglNameExpression>(); FglNameExpression cid; if (FglNameExpression.TryParseNode(parser, out cid)) { node.CursorId = cid; } else { parser.ReportSyntaxError("Invalid declared cursor id found in foreach statement."); } HashSet <TokenKind> inVarMods = new HashSet <TokenKind> { TokenKind.InKeyword, TokenKind.OutKeyword, TokenKind.InOutKeyword }; if (parser.PeekToken(TokenKind.UsingKeyword)) { parser.NextToken(); FglNameExpression inVar; while (FglNameExpression.TryParseNode(parser, out inVar, TokenKind.Comma)) { node.InputVars.Add(inVar); if (inVarMods.Contains(parser.PeekToken().Kind)) { parser.NextToken(); } if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } else { break; } } } if (parser.PeekToken(TokenKind.IntoKeyword)) { parser.NextToken(); FglNameExpression outVar; while (FglNameExpression.TryParseNode(parser, out outVar, TokenKind.Comma)) { node.InputVars.Add(outVar); if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } else { break; } } } node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenKind.WithKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.ReoptimizationKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting keyword \"reoptimization\" in open statement."); } } List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.ForeachKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.ForeachKeyword); prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ForeachKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExits, contextStatementFactories, null, newEndKeywords) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; node.Children.Add(stmtNode.StartIndex, stmtNode); if (statement is ExitStatement && (statement as ExitStatement).ExitType != TokenKind.ForeachKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ExitStatement).ExitType)) { parser.ReportSyntaxError("Invalid exit statement for for loop detected."); } } if (statement is ContinueStatement && (statement as ContinueStatement).ContinueType != TokenKind.ForeachKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ContinueStatement).ContinueType)) { parser.ReportSyntaxError("Invalid continue statement for for loop detected."); } } } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ForeachKeyword, 2))) { parser.ReportSyntaxError("A foreach statement must be terminated with \"end foreach\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'foreach' token node.EndIndex = parser.Token.Span.End; } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out FunctionBlockNode defNode, out int bufferPosition, IModuleResult containingModule, bool abbreviatedParse = false, bool advanceOnEnd = true) { bufferPosition = 0; defNode = null; bool result = false; AccessModifier?accMod = null; string accModToken = null; if (parser.PeekToken(TokenKind.PublicKeyword)) { accMod = AccessModifier.Public; accModToken = parser.PeekToken().Value.ToString(); } else if (parser.PeekToken(TokenKind.PrivateKeyword)) { accMod = AccessModifier.Private; accModToken = parser.PeekToken().Value.ToString(); } uint lookAheadBy = (uint)(accMod.HasValue ? 2 : 1); if (parser.PeekToken(TokenKind.FunctionKeyword, lookAheadBy)) { result = true; defNode = new FunctionBlockNode(); if (accMod.HasValue) { parser.NextToken(); defNode.AccessModifier = accMod.Value; defNode.StartIndex = parser.Token.Span.Start; } else { defNode.AccessModifier = AccessModifier.Public; } parser.NextToken(); // move past the Function keyword if (!accMod.HasValue) { defNode.StartIndex = parser.Token.Span.Start; } // get the name if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.NextToken(); defNode.Name = parser.Token.Token.Value.ToString(); defNode.LocationIndex = parser.Token.Span.Start; defNode.DecoratorEnd = parser.Token.Span.End; } else { parser.ReportSyntaxError("A function must have a name."); } if (!parser.PeekToken(TokenKind.LeftParenthesis)) { parser.ReportSyntaxError("A function must specify zero or more parameters in the form: ([param1][,...])"); } else { parser.NextToken(); } bool paramsParsed = false; if (parser.LanguageVersion >= GeneroLanguageVersion.V310) { while (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { var paramName = parser.PeekTokenWithSpan(); string errMsg; if (!defNode.AddArgument(paramName, out errMsg)) { parser.ReportSyntaxError(errMsg); } // try parsing the parameters as variable definitions VariableDefinitionNode varDefNode = null; if (VariableDefinitionNode.TryParseNode(parser, out varDefNode, defNode.BindArgument, false, false)) { defNode.Children.Add(varDefNode.StartIndex, varDefNode); foreach (var vardef in varDefNode.VariableDefinitions) { vardef.Scope = "local variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.Variables.Add(vardef.Name, vardef); } else { parser.ReportSyntaxError(vardef.LocationIndex, vardef.LocationIndex + vardef.Name.Length, string.Format("Variable {0} defined more than once.", vardef.Name), Severity.Error); } } paramsParsed = true; } if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } } } if (!paramsParsed) { // get the parameters while (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.NextToken(); string errMsg; if (!defNode.AddArgument(parser.Token, out errMsg)) { parser.ReportSyntaxError(errMsg); } if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } // TODO: probably need to handle "end" "function" case...won't right now } } if (!parser.PeekToken(TokenKind.RightParenthesis)) { parser.ReportSyntaxError("A function must specify zero or more parameters in the form: ([param1][,...])"); } else { parser.NextToken(); } if (parser.LanguageVersion >= GeneroLanguageVersion.V310) { ReturnsStatement returnsStatement; if (ReturnsStatement.TryParseNode(parser, out returnsStatement)) { defNode._explicitReturns = new List <TypeReference>(); foreach (var ret in returnsStatement.ReturnTypes) { defNode._explicitReturns.Add(ret); } } } List <List <TokenKind> > breakSequences = new List <List <TokenKind> >(Genero4glAst.ValidStatementKeywords .Where(x => x != TokenKind.EndKeyword && x != TokenKind.FunctionKeyword) .Select(x => new List <TokenKind> { x })) { new List <TokenKind> { TokenKind.EndKeyword, TokenKind.FunctionKeyword } }; List <TokenKind> validExits = new List <TokenKind> { TokenKind.ProgramKeyword }; HashSet <TokenKind> endKeywords = new HashSet <TokenKind> { TokenKind.FunctionKeyword }; // try to parse one or more declaration statements while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.FunctionKeyword, 2))) { DefineNode defineNode; TypeDefNode typeNode; ConstantDefNode constNode; bool matchedBreakSequence = false; switch (parser.PeekToken().Kind) { case TokenKind.TypeKeyword: { if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null) { defNode.Children.Add(typeNode.StartIndex, typeNode); foreach (var def in typeNode.GetDefinitions()) { def.Scope = "local type"; if (!defNode.Types.ContainsKey(def.Name)) { defNode.Types.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Type {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.ConstantKeyword: { if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null) { defNode.Children.Add(constNode.StartIndex, constNode); foreach (var def in constNode.GetDefinitions()) { def.Scope = "local constant"; if (!defNode.Constants.ContainsKey(def.Name)) { defNode.Constants.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Constant {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.DefineKeyword: { if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences, defNode.BindArgument) && defineNode != null) { defNode.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "local variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.Variables.Add(vardef.Name, vardef); } else { parser.ReportSyntaxError(vardef.LocationIndex, vardef.LocationIndex + vardef.Name.Length, string.Format("Variable {0} defined more than once.", vardef.Name), Severity.Error); } } } } break; } default: { FglStatement statement; List <Func <PrepareStatement, bool> > prepBinders = new List <Func <PrepareStatement, bool> >(); prepBinders.Add(defNode.BindPrepareCursorFromIdentifier); if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepBinders, defNode.StoreReturnStatement, defNode.AddLimitedScopeVariable, abbreviatedParse, validExits, null, null, endKeywords)) { AstNode4gl stmtNode = statement as AstNode4gl; if (stmtNode != null && !defNode.Children.ContainsKey(stmtNode.StartIndex)) { defNode.Children.Add(stmtNode.StartIndex, stmtNode); } continue; } break; } } if (parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.FunctionKeyword, 2))) { break; } // if a break sequence was matched, we don't want to advance the token if (!matchedBreakSequence) { // TODO: not sure whether to break or keep going...for right now, let's keep going until we hit the end keyword parser.NextToken(); } } if (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); if (parser.PeekToken(TokenKind.FunctionKeyword)) { var tokSpan = parser.PeekTokenWithSpan(); bufferPosition = tokSpan.BufferPosition + tokSpan.Span.Length; if (advanceOnEnd) { parser.NextToken(); } defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; } else { parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of function definition."); } } else { parser.ReportSyntaxError("Unexpected end of function definition"); } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out WhileStatement node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.WhileKeyword)) { result = true; node = new WhileStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; ExpressionNode conditionExpr; if (!FglExpressionNode.TryGetExpressionNode(parser, out conditionExpr, Genero4glAst.ValidStatementKeywords.ToList(), expressionOptions)) { parser.ReportSyntaxError("A while statement must have a condition expression."); } else { node.ConditionExpression = conditionExpr; } node.DecoratorEnd = parser.Token.Span.End; List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.WhileKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.WhileKeyword); prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.WhileKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExits, contextStatementFactories, expressionOptions, newEndKeywords) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; node.Children.Add(stmtNode.StartIndex, stmtNode); if (statement is ExitStatement && (statement as ExitStatement).ExitType != TokenKind.WhileKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ExitStatement).ExitType)) { parser.ReportSyntaxError("Invalid exit statement for while loop detected."); } } if (statement is ContinueStatement && (statement as ContinueStatement).ContinueType != TokenKind.WhileKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ContinueStatement).ContinueType)) { parser.ReportSyntaxError("Invalid continue statement for while loop detected."); } } } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.WhileKeyword, 2))) { parser.ReportSyntaxError("A while statement must be terminated with \"end while\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'while' token node.EndIndex = parser.Token.Span.End; } } return(result); }
public static bool TryParserNode(Genero4glParser parser, out ForStatement node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.ForKeyword)) { result = true; node = new ForStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; ExpressionNode counterVar; if (FglExpressionNode.TryGetExpressionNode(parser, out counterVar, new List <TokenKind> { TokenKind.Equals })) { node.CounterVariable = counterVar; } else { parser.ReportSyntaxError("Invalid expression found in for statement"); } if (parser.PeekToken(TokenKind.Equals)) { parser.NextToken(); } else { parser.ReportSyntaxError("For statement missing counter variable assignment."); } ExpressionNode startValue; if (FglExpressionNode.TryGetExpressionNode(parser, out startValue, new List <TokenKind> { TokenKind.ToKeyword })) { node.StartValueExpresison = startValue; } else { parser.ReportSyntaxError("Invalid expression found in for statement"); } if (parser.PeekToken(TokenKind.ToKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("For statement missing \"to\" keyword."); } List <TokenKind> keywords = new List <TokenKind>(Genero4glAst.ValidStatementKeywords); keywords.Add(TokenKind.StepKeyword); ExpressionNode endValue; if (FglExpressionNode.TryGetExpressionNode(parser, out endValue, keywords)) { node.EndValueExpression = endValue; } else { parser.ReportSyntaxError("Invalid expression found in for statement"); } if (parser.PeekToken(TokenKind.StepKeyword)) { parser.NextToken(); ExpressionNode stepExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out stepExpr)) { node.StepValue = stepExpr; } else { parser.ReportSyntaxError("Invalid step expression found."); } //bool negative = false; //if (parser.PeekToken(TokenKind.Subtract)) //{ // negative = true; // parser.NextToken(); //} //if(parser.PeekToken(TokenCategory.NumericLiteral)) //{ // parser.NextToken(); // int temp; // if(int.TryParse(parser.Token.Token.Value.ToString(), out temp)) // { // node.StepValue = temp; // if (negative) // node.StepValue = -(node.StepValue); // } // else // { // parser.ReportSyntaxError("Invalid step value found."); // } //} //else //{ // parser.ReportSyntaxError("Invalid step value found."); //} } node.DecoratorEnd = parser.Token.Span.End; List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.ForKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.ForKeyword); prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ForKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExits, contextStatementFactories, expressionOptions, newEndKeywords) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; node.Children.Add(stmtNode.StartIndex, stmtNode); if (statement is ExitStatement && (statement as ExitStatement).ExitType != TokenKind.ForKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ExitStatement).ExitType)) { parser.ReportSyntaxError("Invalid exit statement for for loop detected."); } } if (statement is ContinueStatement && (statement as ContinueStatement).ContinueType != TokenKind.ForKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ContinueStatement).ContinueType)) { parser.ReportSyntaxError("Invalid continue statement for for loop detected."); } } } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ForKeyword, 2))) { parser.ReportSyntaxError("A for statement must be terminated with \"end for\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'for' token node.EndIndex = parser.Token.Span.End; } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out MainBlockNode defNode, IModuleResult containingModule) { defNode = null; bool result = false; if (parser.PeekToken(TokenKind.MainKeyword)) { result = true; defNode = new MainBlockNode(); parser.NextToken(); defNode.Name = parser.Token.Token.Value.ToString(); defNode.StartIndex = parser.Token.Span.Start; defNode.DecoratorEnd = defNode.StartIndex + 4; defNode.AccessModifier = AccessModifier.Private; List <List <TokenKind> > breakSequences = new List <List <TokenKind> >(Genero4glAst.ValidStatementKeywords .Where(x => x != TokenKind.EndKeyword && x != TokenKind.MainKeyword) .Select(x => new List <TokenKind> { x })) { new List <TokenKind> { TokenKind.EndKeyword, TokenKind.MainKeyword } }; List <TokenKind> validExits = new List <TokenKind> { TokenKind.ProgramKeyword }; HashSet <TokenKind> endKeywords = new HashSet <TokenKind> { TokenKind.MainKeyword }; bool fglStatement = false; // try to parse one or more declaration statements while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.MainKeyword, 2))) { fglStatement = false; DefineNode defineNode; TypeDefNode typeNode; ConstantDefNode constNode; bool matchedBreakSequence = false; switch (parser.PeekToken().Kind) { case TokenKind.TypeKeyword: { if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null) { defNode.Children.Add(typeNode.StartIndex, typeNode); foreach (var def in typeNode.GetDefinitions()) { def.Scope = "local type"; if (!defNode.Types.ContainsKey(def.Name)) { defNode.Types.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Type {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.ConstantKeyword: { if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null) { defNode.Children.Add(constNode.StartIndex, constNode); foreach (var def in constNode.GetDefinitions()) { def.Scope = "local constant"; if (!defNode.Constants.ContainsKey(def.Name)) { defNode.Constants.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Constant {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.DefineKeyword: { if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences) && defineNode != null) { defNode.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "local variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.Variables.Add(vardef.Name, vardef); } else { parser.ReportSyntaxError(vardef.LocationIndex, vardef.LocationIndex + vardef.Name.Length, string.Format("Variable {0} defined more than once.", vardef.Name), Severity.Error); } } } } break; } default: { FglStatement statement; List <Func <PrepareStatement, bool> > prepBinders = new List <Func <PrepareStatement, bool> >(); prepBinders.Add(defNode.BindPrepareCursorFromIdentifier); if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepBinders, defNode.StoreReturnStatement, defNode.AddLimitedScopeVariable, false, validExits, null, null, endKeywords) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; defNode.Children.Add(stmtNode.StartIndex, stmtNode); fglStatement = true; } break; } } if (parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.MainKeyword, 2))) { break; } // if a break sequence was matched, we don't want to advance the token if (!matchedBreakSequence && !fglStatement) { // TODO: not sure whether to break or keep going...for right now, let's keep going until we hit the end keyword parser.NextToken(); } } if (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); if (parser.PeekToken(TokenKind.MainKeyword)) { parser.NextToken(); defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; } else { parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of main definition."); } } else { parser.ReportSyntaxError("Unexpected end of main definition"); } } return(result); }