예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }