Beispiel #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);
        }
Beispiel #2
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);
        }