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 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 IfStatement 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.IfKeyword)) { result = true; node = new IfStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; ExpressionNode conditionExpr; if (!FglExpressionNode.TryGetExpressionNode(parser, out conditionExpr, new List <TokenKind> { TokenKind.ThenKeyword }, expressionOptions)) { parser.ReportSyntaxError("An if statement must have a condition expression."); } else { node.ConditionExpression = conditionExpr; } if (parser.PeekToken(TokenKind.ThenKeyword)) { parser.NextToken(); node.DecoratorEnd = parser.Token.Span.End; HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.IfKeyword); IfBlockContentsNode ifBlock; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); if (IfBlockContentsNode.TryParseNode(parser, out ifBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, newEndKeywords)) { if (ifBlock != null) { node.Children.Add(ifBlock.StartIndex, ifBlock); } } if (parser.PeekToken(TokenKind.ElseKeyword)) { parser.NextToken(); ElseBlockContentsNode elseBlock; if (ElseBlockContentsNode.TryParseNode(parser, out elseBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, newEndKeywords)) { if (elseBlock != null) { node.Children.Add(elseBlock.StartIndex, elseBlock); // Add the span of "else" to the additional decorators node.AdditionalDecoratorRanges.Add(elseBlock.StartIndex, elseBlock.StartIndex + 4); } } } prepStatementBinders.RemoveAt(0); if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.IfKeyword, 2))) { parser.ReportSyntaxError("An if statement must be terminated with \"end if\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'if' token node.EndIndex = parser.Token.Span.End; } } else { parser.ReportSyntaxError("An if statement must have a \"then\" keyword prior to containing code."); } } return(result); }
public bool TryParseNode(Genero4glParser parser, out FglStatement node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, bool returnStatementsOnly = false, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (returnStatementsOnly) { if (parser.PeekToken(TokenKind.ReturnKeyword)) { ReturnStatement retStmt; if ((result = ReturnStatement.TryParseNode(parser, out retStmt))) { node = retStmt; } } return(result); } if (contextStatementFactories != null) { foreach (var context in contextStatementFactories) { node = context(parser); if (node != null) { break; } } if (node != null) { return(true); } } switch (parser.PeekToken().Kind) { case TokenKind.LetKeyword: { LetStatement letStmt; if ((result = LetStatement.TryParseNode(parser, out letStmt, expressionOptions))) { node = letStmt; } break; } case TokenKind.DeclareKeyword: { DeclareStatement declStmt; if ((result = DeclareStatement.TryParseNode(parser, out declStmt, containingModule))) { node = declStmt; } break; } case TokenKind.DeferKeyword: { DeferStatementNode deferStmt; if ((result = DeferStatementNode.TryParseNode(parser, out deferStmt))) { node = deferStmt; } break; } case TokenKind.PrepareKeyword: { PrepareStatement prepStmt; if ((result = PrepareStatement.TryParseNode(parser, out prepStmt, containingModule))) { node = prepStmt; foreach (var binder in prepStatementBinders) { if (binder(prepStmt)) { break; } } } break; } case TokenKind.SqlKeyword: { SqlBlockNode sqlStmt; if ((result = SqlBlockNode.TryParseSqlNode(parser, out sqlStmt))) { node = sqlStmt; } break; } case TokenKind.ReturnKeyword: { ReturnStatement retStmt; if ((result = ReturnStatement.TryParseNode(parser, out retStmt))) { if (returnStatementBinder != null) { var parseResult = returnStatementBinder(retStmt); if (!parseResult.Success && !string.IsNullOrWhiteSpace(parseResult.ErrorMessage)) { parser.ReportSyntaxError(parseResult.ErrorMessage); } } node = retStmt; } break; } case TokenKind.CallKeyword: { CallStatement callStmt; if ((result = CallStatement.TryParseNode(parser, out callStmt))) { node = callStmt; } break; } case TokenKind.IfKeyword: { IfStatement ifStmt; if ((result = IfStatement.TryParseNode(parser, out ifStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = ifStmt; } break; } case TokenKind.WhileKeyword: { WhileStatement whileStmt; if ((result = WhileStatement.TryParseNode(parser, out whileStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = whileStmt; } break; } case TokenKind.ExitKeyword: { ExitStatement exitStatement; if ((result = ExitStatement.TryParseNode(parser, out exitStatement))) { node = exitStatement; } break; } case TokenKind.ContinueKeyword: { ContinueStatement contStmt; if ((result = ContinueStatement.TryParseNode(parser, out contStmt))) { node = contStmt; } break; } case TokenKind.WheneverKeyword: { WheneverStatement wheneverStmt; if ((result = WheneverStatement.TryParseNode(parser, out wheneverStmt))) { node = wheneverStmt; } break; } case TokenKind.ForKeyword: { ForStatement forStmt; if ((result = ForStatement.TryParserNode(parser, out forStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = forStmt; } break; } case TokenKind.CaseKeyword: { CaseStatement caseStmt; if ((result = CaseStatement.TryParseNode(parser, out caseStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = caseStmt; } break; } case TokenKind.InitializeKeyword: { InitializeStatement initStmt; if ((result = InitializeStatement.TryParseNode(parser, out initStmt))) { node = initStmt; } break; } case TokenKind.LocateKeyword: { LocateStatement locateStmt; if ((result = LocateStatement.TryParseNode(parser, out locateStmt))) { node = locateStmt; } break; } case TokenKind.FreeKeyword: { FreeStatement freeStmt; if ((result = FreeStatement.TryParseNode(parser, out freeStmt))) { node = freeStmt; } break; } case TokenKind.GotoKeyword: { GotoStatement gotoStmt; if ((result = GotoStatement.TryParseNode(parser, out gotoStmt))) { node = gotoStmt; } break; } case TokenKind.LabelKeyword: { LabelStatement labelStmt; if ((result = LabelStatement.TryParseNode(parser, out labelStmt))) { node = labelStmt; } break; } case TokenKind.SleepKeyword: { SleepStatement sleepStmt; if ((result = SleepStatement.TryParseNode(parser, out sleepStmt))) { node = sleepStmt; } break; } case TokenKind.TryKeyword: { TryCatchStatement tryStmt; if ((result = TryCatchStatement.TryParseNode(parser, out tryStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = tryStmt; } break; } case TokenKind.ValidateKeyword: { ValidateStatement validateStmt; if ((result = ValidateStatement.TryParseNode(parser, out validateStmt))) { node = validateStmt; } break; } case TokenKind.OptionsKeyword: { OptionsStatement optionsStmt; if ((result = OptionsStatement.TryParseNode(parser, out optionsStmt))) { node = optionsStmt; } break; } case TokenKind.ExecuteKeyword: { ExecuteStatement exeStmt; if ((result = ExecuteStatement.TryParseNode(parser, out exeStmt))) { node = exeStmt; } break; } case TokenKind.OpenKeyword: { OpenStatement openStmt; if ((result = OpenStatement.TryParseNode(parser, out openStmt))) { node = openStmt; } break; } case TokenKind.FetchKeyword: { FetchStatement fetchStmt; if ((result = FetchStatement.TryParseNode(parser, out fetchStmt))) { node = fetchStmt; } break; } case TokenKind.CloseKeyword: { CloseStatement closeStmt; if ((result = CloseStatement.TryParseNode(parser, out closeStmt))) { node = closeStmt; } break; } case TokenKind.ClearKeyword: { ClearStatement clearStmt; if ((result = ClearStatement.TryParseNode(parser, out clearStmt))) { node = clearStmt; } break; } case TokenKind.ForeachKeyword: { ForeachStatement foreachStmt; if ((result = ForeachStatement.TryParseNode(parser, out foreachStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = foreachStmt; } break; } case TokenKind.MessageKeyword: { MessageStatement msgStmt; if ((result = MessageStatement.TryParseNode(parser, out msgStmt))) { node = msgStmt; } break; } case TokenKind.MenuKeyword: { MenuBlock menuStmt; if ((result = MenuBlock.TryParseNode(parser, out menuStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = menuStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.InputKeyword: { InputBlock inputStmt; if ((result = InputBlock.TryParseNode(parser, out inputStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = inputStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.ConstructKeyword: { ConstructBlock constructStmt; if ((result = ConstructBlock.TryParseNode(parser, out constructStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = constructStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.FlushKeyword: { FlushStatement flushStmt; if ((result = FlushStatement.TryParseNode(parser, out flushStmt))) { node = flushStmt; } break; } case TokenKind.DisplayKeyword: { DisplayBlock dispStmt; if ((result = DisplayBlock.TryParseNode(parser, out dispStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = dispStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.PromptKeyword: { PromptStatement promptStmt; if ((result = PromptStatement.TryParseNode(parser, out promptStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = promptStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.DialogKeyword: { DialogBlock dialogBlock; if ((result = DialogBlock.TryParseNode(parser, out dialogBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = dialogBlock; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.AcceptKeyword: { AcceptStatement acceptStmt; if ((result = AcceptStatement.TryParseNode(parser, out acceptStmt))) { node = acceptStmt; } break; } case TokenKind.LoadKeyword: { LoadStatement loadStmt; if ((result = LoadStatement.TryParseNode(parser, out loadStmt))) { node = loadStmt; } break; } case TokenKind.CreateKeyword: { CreateStatement createStmt; if ((result = CreateStatement.TryParseNode(parser, out createStmt, containingModule))) { node = createStmt; } break; } case TokenKind.BreakpointKeyword: { BreakpointStatement brkStmt; if ((result = BreakpointStatement.TryParseNode(parser, out brkStmt))) { node = brkStmt; } break; } case TokenKind.OutputKeyword: { OutputToReportStatement outRpt; if ((result = OutputToReportStatement.TryParseNode(parser, out outRpt))) { node = outRpt; } break; } case TokenKind.StartKeyword: { StartReportStatement startRpt; if ((result = StartReportStatement.TryParseNode(parser, out startRpt))) { node = startRpt; } break; } case TokenKind.FinishKeyword: { FinishReportStatement finRpt; if ((result = FinishReportStatement.TryParseNode(parser, out finRpt))) { node = finRpt; } break; } case TokenKind.TerminateKeyword: { TerminateReportStatement termRpt; if ((result = TerminateReportStatement.TryParseNode(parser, out termRpt))) { node = termRpt; } break; } default: { if (SqlStatementFactory.IsValidStatementStart(parser.PeekToken().Kind)) { bool dummy; result = SqlStatementFactory.TryParseSqlStatement(parser, out node, out dummy); } break; } } if (result) { // check for semicolon if (parser.PeekToken(TokenKind.Semicolon)) { parser.NextToken(); } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out CaseStatement 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.CaseKeyword)) { result = true; node = new CaseStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; if (!parser.PeekToken(TokenKind.WhenKeyword)) { ExpressionNode tempExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out tempExpr, new List <TokenKind> { TokenKind.WhenKeyword })) { node.ConditionExpression = tempExpr; } else { parser.ReportSyntaxError("Invalid conditional expression found in case statement"); } } node.DecoratorEnd = parser.Token.Span.End; List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.CaseKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.CaseKeyword); // need to allow multiple when statements bool whenCases = true; while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.CaseKeyword, 2))) { WhenStatement whenStmt; if (WhenStatement.TryParseNode(parser, out whenStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, expressionOptions, newEndKeywords) && whenStmt != null) { if (whenCases) { node.Children.Add(whenStmt.StartIndex, whenStmt); } else { parser.ReportSyntaxError("A when case cannot come after an otherwise case block."); break; } } else { OtherwiseStatement otherStmt; if (OtherwiseStatement.TryParseNode(parser, out otherStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, expressionOptions, newEndKeywords) && otherStmt != null) { whenCases = false; node.Children.Add(otherStmt.StartIndex, otherStmt); } else { parser.ReportSyntaxError("Invalid statement detected within case statement block."); break; } } } if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.CaseKeyword, 2))) { parser.ReportSyntaxError("A case statement must be terminated with \"end case\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'case' token node.EndIndex = parser.Token.Span.End; } } return(result); }
public static bool TryParseExpression(IParser parser, out FunctionCallExpressionNode node, out FglNameExpression nonFunctionCallName, bool leftParenRequired = false, ExpressionParsingOptions options = null) { if (options == null) { options = new ExpressionParsingOptions(); } node = null; nonFunctionCallName = null; bool result = false; FglNameExpression name; if (FglNameExpression.TryParseNode(parser, out name, TokenKind.LeftParenthesis)) { node = new FunctionCallExpressionNode(); node.StartIndex = name.StartIndex; node.Function = name; // get the left paren if (parser.PeekToken(TokenKind.LeftParenthesis)) { result = true; parser.NextToken(); if (!options.AllowAnythingForFunctionParams) { // Parameters can be any expression, comma seperated ExpressionNode expr; while (FglExpressionNode.TryGetExpressionNode(parser, out expr, new List <TokenKind> { TokenKind.Comma, TokenKind.RightParenthesis }, options)) { node.Parameters.Add(expr); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } // get the right paren if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); // TODO: not sure if this is needed } else { parser.ReportSyntaxError("Call statement missing right parenthesis."); } if (parser.PeekToken(TokenKind.Dot)) { parser.NextToken(); // get the dotted member access (which could end up being another function call, so this needs to allow recursion) if (parser.PeekToken(TokenKind.Multiply)) { parser.NextToken(); node.Children.Add(parser.Token.Span.Start, new TokenExpressionNode(parser.Token)); } else { FunctionCallExpressionNode funcCall; FglNameExpression nonFuncCallName; if (FunctionCallExpressionNode.TryParseExpression(parser, out funcCall, out nonFuncCallName, false, options)) { node.Children.Add(funcCall.StartIndex, funcCall); } else if (nonFuncCallName != null) { node.Children.Add(nonFuncCallName.StartIndex, nonFuncCallName); } else { parser.NextToken(); node.Children.Add(parser.Token.Span.Start, new TokenExpressionNode(parser.Token)); } } } } else { // just int rightParenLevel = 1; Token tok; bool done = false; while (true) { tok = parser.NextToken(); switch (tok.Kind) { case TokenKind.LeftParenthesis: rightParenLevel++; break; case TokenKind.RightParenthesis: rightParenLevel--; if (rightParenLevel == 0) { done = true; } break; case TokenKind.EndOfFile: done = true; break; default: node.AnythingParameters.Add(tok); break; } if (done) { break; } } } node.EndIndex = parser.Token.Span.End; } else { if (leftParenRequired) { result = true; parser.ReportSyntaxError("Call statement missing left parenthesis."); } else { nonFunctionCallName = name; node = null; } } } return(result); }
public static bool TryGetExpressionNode(IParser parser, out ExpressionNode node, List <TokenKind> breakTokens = null, ExpressionParsingOptions options = null) { if (options == null) { options = new ExpressionParsingOptions(); } node = null; bool result = false; bool start = true; bool requireExpression = false; TokenExpressionNode startingToken = null; while (true) { // First check for allowed pre-expression tokens if (_preExpressionTokens.Contains(parser.PeekToken().Kind)) { parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } requireExpression = true; } if (parser.PeekToken(TokenKind.LeftParenthesis)) { ParenWrappedExpressionNode parenExpr; if (ParenWrappedExpressionNode.TryParseExpression(parser, out parenExpr, options)) { if (node == null) { node = parenExpr; } else { node.AppendExpression(parenExpr); } result = true; } else { parser.ReportSyntaxError("Paren-nested expression expected."); } } else if (parser.PeekToken(TokenKind.LeftBracket)) { BracketWrappedExpressionNode brackNode; if (BracketWrappedExpressionNode.TryParseNode(parser, out brackNode)) { if (node == null) { node = brackNode; } else { node.AppendExpression(brackNode); } result = true; } else { parser.ReportSyntaxError("Bracket-nested expression expected."); } } else if (parser.PeekToken(TokenCategory.StringLiteral) || parser.PeekToken(TokenCategory.CharacterLiteral) || parser.PeekToken(TokenCategory.IncompleteMultiLineStringLiteral)) { result = true; parser.NextToken(); if (node == null) { node = new StringExpressionNode(parser.Token); } else { node.AppendExpression(new StringExpressionNode(parser.Token)); } } else if (parser.PeekToken(TokenCategory.NumericLiteral)) { result = true; parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } else if (parser.PeekToken(TokenKind.CurrentKeyword)) { result = true; parser.NextToken(); int currentExprStart = parser.Token.Span.Start; string currentTypeConstraint; if (TypeConstraints.VerifyValidConstraint(parser, out currentTypeConstraint, TokenKind.CurrentKeyword, true)) { result = true; StringExpressionNode strExpr = new StringExpressionNode(string.Format("current {0}", currentTypeConstraint)); strExpr.StartIndex = currentExprStart; strExpr.EndIndex = parser.Token.Span.End; if (node == null) { node = strExpr; } else { node.AppendExpression(strExpr); } } else { if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } } else if (parser.PeekToken(TokenKind.IntervalKeyword)) { parser.NextToken(); TokenExpressionNode intervalNode = new TokenExpressionNode(parser.Token); if (node == null) { node = intervalNode; } else { node.AppendExpression(intervalNode); } if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); while (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.Token.Token.Kind == TokenKind.RightParenthesis) { break; } } string intervalString; if (TypeConstraints.VerifyValidConstraint(parser, out intervalString, TokenKind.IntervalKeyword, true)) { result = true; node.AppendExpression(new StringExpressionNode(intervalString)); } else { parser.ReportSyntaxError("Invalid interval expression found."); } } } else if (parser.PeekToken(TokenKind.SelectKeyword) && options.AllowNestedSelectStatement) { FglStatement selStmt; bool dummy; if (SqlStatementFactory.TryParseSqlStatement(parser, out selStmt, out dummy)) { result = true; if (node == null) { node = new FglStatementExpression(selStmt); } else { node.AppendExpression(new FglStatementExpression(selStmt)); } } else { parser.ReportSyntaxError("Invalid select statement found in expression."); } } else if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { bool isCustomExpression = false; if (options != null && options.AdditionalExpressionParsers != null) { ExpressionNode parsedExpr; foreach (var exprParser in options.AdditionalExpressionParsers) { if ((parsedExpr = exprParser(parser)) != null) { result = true; if (node == null) { node = parsedExpr; } else { node.AppendExpression(parsedExpr); } isCustomExpression = true; } } } if (!isCustomExpression) { FunctionCallExpressionNode funcCall; FglNameExpression nonFuncCallName; if (FunctionCallExpressionNode.TryParseExpression(parser, out funcCall, out nonFuncCallName, false, options)) { result = true; if (node == null) { node = funcCall; } else { node.AppendExpression(funcCall); } } else if (nonFuncCallName != null) { bool isDatetime = false; var dtToken = Tokens.GetToken(nonFuncCallName.Name); if (dtToken != null) { if (TypeConstraints.DateTimeQualifiers.Contains(dtToken.Kind)) { string dtString; isDatetime = true; if (TypeConstraints.VerifyValidConstraint(parser, out dtString, TokenKind.DatetimeKeyword, true, dtToken.Kind)) { result = true; var strExpr = new StringExpressionNode(dtString); if (node == null) { node = strExpr; } else { node.AppendExpression(strExpr); } } else { isDatetime = false; } } } if (!isDatetime) { // it's a name expression result = true; if (node == null) { node = nonFuncCallName; } else { node.AppendExpression(nonFuncCallName); } } } else { result = true; parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } } } else if (parser.PeekToken(TokenKind.Multiply) && options.AllowStarParam) { result = true; parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } else if (parser.PeekToken(TokenKind.QuestionMark) && options.AllowQuestionMark) { parser.NextToken(); if (node == null) { parser.ReportSyntaxError("Invalid token '?' found in expression."); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } else { if (requireExpression) { var tok = parser.PeekToken(); if (breakTokens != null && !breakTokens.Contains(tok.Kind)) { parser.ReportSyntaxError("Invalid token type found in expression."); } else { parser.ReportSyntaxError("Expression required."); } } break; } requireExpression = false; Token nextTok = parser.PeekToken(); bool isOperator = true; while (isOperator && !requireExpression) { if ((breakTokens == null || (breakTokens != null && !breakTokens.Contains(nextTok.Kind))) && nextTok.Kind >= TokenKind.FirstOperator && nextTok.Kind <= TokenKind.LastOperator) { parser.NextToken(); // TODO: not sure if we want to do more analysis on what operators can start an expression if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } switch (parser.Token.Token.Kind) { case TokenKind.LessThan: // check for '<=' or '<>' if (parser.PeekToken(TokenKind.Equals) || parser.PeekToken(TokenKind.GreaterThan)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.GreaterThan: // check for '>=' if (parser.PeekToken(TokenKind.Equals)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.Exclamation: // check for '!=' if (parser.PeekToken(TokenKind.Equals)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("Invalid token '!' found in expression."); } break; case TokenKind.Equals: // check for '==' if (parser.PeekToken(TokenKind.Equals)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.SingleBar: // check for '||' if (parser.PeekToken(TokenKind.SingleBar)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("Invalid token '|' found in expression."); } break; } requireExpression = true; } else { // check for non-symbol operators switch (nextTok.Kind) { case TokenKind.DoubleBar: case TokenKind.AsKeyword: case TokenKind.AndKeyword: case TokenKind.OrKeyword: case TokenKind.ModKeyword: case TokenKind.UsingKeyword: case TokenKind.InstanceOfKeyword: case TokenKind.UnitsKeyword: case TokenKind.LikeKeyword: case TokenKind.MatchesKeyword: case TokenKind.ThroughKeyword: case TokenKind.ThruKeyword: case TokenKind.BetweenKeyword: { // require another expression requireExpression = true; parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.ClippedKeyword: case TokenKind.SpacesKeyword: { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.IsKeyword: { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.PeekToken(TokenKind.NotKeyword)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } if (parser.PeekToken(TokenKind.NullKeyword)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("NULL keyword required in expression."); } } break; case TokenKind.NotKeyword: { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.PeekToken(TokenKind.LikeKeyword) || parser.PeekToken(TokenKind.MatchesKeyword) || parser.PeekToken(TokenKind.InKeyword)) { // require another expression requireExpression = true; parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("LIKE or MATCHES keyword required in expression."); } } break; default: { isOperator = false; break; } } if (!isOperator) { break; } else { nextTok = parser.PeekToken(); if (nextTok.Kind == TokenKind.EndOfFile) { break; } } } } if (!requireExpression) { break; } } if (result && node != null) { node.EndIndex = parser.Token.Span.End; } return(result); }
public static bool TryParseExpression(IParser parser, out ParenWrappedExpressionNode node, ExpressionParsingOptions options = null) { if (options == null) { options = new ExpressionParsingOptions(); } node = null; bool result = false; if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); node = new ParenWrappedExpressionNode(); result = true; node.StartIndex = parser.Token.Span.Start; if (!options.AllowAnythingForFunctionParams) { ExpressionNode exprNode; if (!FglExpressionNode.TryGetExpressionNode(parser, out exprNode, new List <TokenKind> { TokenKind.RightParenthesis }, options)) { parser.ReportSyntaxError("Invalid expression found within parentheses."); } else { node.InnerExpression = exprNode; } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); node.EndIndex = parser.Token.Span.End; } else { parser.ReportSyntaxError("Right parenthesis not found."); } } else { // just int rightParenLevel = 1; Token tok; bool done = false; while (true) { tok = parser.NextToken(); switch (tok.Kind) { case TokenKind.LeftParenthesis: rightParenLevel++; break; case TokenKind.RightParenthesis: rightParenLevel--; if (rightParenLevel == 0) { done = true; } break; case TokenKind.EndOfFile: done = true; break; default: node.AnythingTokens.Add(tok); break; } if (done) { break; } } } } 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 TryParseNode(Genero4glParser parser, out LetStatement defNode, ExpressionParsingOptions expressionOptions = null) { defNode = null; bool result = false; if (parser.PeekToken(TokenKind.LetKeyword)) { result = true; defNode = new LetStatement(); parser.NextToken(); defNode.StartIndex = parser.Token.Span.Start; FglNameExpression name; if (!FglNameExpression.TryParseNode(parser, out name, TokenKind.Equals)) { parser.ReportSyntaxError("Unexpected token found in let statement, expecting name expression."); } else { defNode.Variable = name; } if (!parser.PeekToken(TokenKind.Equals)) { parser.ReportSyntaxError("Assignment statement is missing an assignment operator."); } else { parser.NextToken(); // get the expression(s) ExpressionNode mainExpression = null; while (true) { ExpressionNode expr; if (!FglExpressionNode.TryGetExpressionNode(parser, out expr, null, expressionOptions)) { parser.ReportSyntaxError("Assignment statement must have one or more comma-separated expressions."); break; } if (mainExpression == null) { mainExpression = expr; } else { mainExpression.AppendExpression(expr); } if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } if (mainExpression != null) { defNode.Children.Add(mainExpression.StartIndex, mainExpression); defNode.EndIndex = mainExpression.EndIndex; defNode.IsComplete = true; } } } 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); }