Esempio n. 1
0
        public static bool TryParseNode(Genero4glParser parser, out ReportBlockNode defNode, IModuleResult containingModule)
        {
            defNode = null;
            bool           result      = false;
            AccessModifier?accMod      = null;
            string         accModToken = null;

            if (parser.PeekToken(TokenKind.PublicKeyword))
            {
                accMod      = AccessModifier.Public;
                accModToken = parser.PeekToken().Value.ToString();
            }
            else if (parser.PeekToken(TokenKind.PrivateKeyword))
            {
                accMod      = AccessModifier.Private;
                accModToken = parser.PeekToken().Value.ToString();
            }

            uint lookAheadBy = (uint)(accMod.HasValue ? 2 : 1);

            if (parser.PeekToken(TokenKind.ReportKeyword, lookAheadBy))
            {
                result  = true;
                defNode = new ReportBlockNode();
                if (accMod.HasValue)
                {
                    parser.NextToken();
                    defNode.AccessModifier = accMod.Value;
                }
                else
                {
                    defNode.AccessModifier = AccessModifier.Public;
                }

                parser.NextToken(); // move past the Function keyword
                defNode.StartIndex    = parser.Token.Span.Start;
                defNode.OrderVarNames = new List <FglNameExpression>();

                // get the name
                if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                {
                    parser.NextToken();
                    defNode.Name          = parser.Token.Token.Value.ToString();
                    defNode.LocationIndex = parser.Token.Span.Start;
                    defNode.DecoratorEnd  = parser.Token.Span.End;
                }
                else
                {
                    parser.ReportSyntaxError("A report must have a name.");
                }

                if (!parser.PeekToken(TokenKind.LeftParenthesis))
                {
                    parser.ReportSyntaxError("A report must specify zero or more parameters in the form: ([param1][,...])");
                }
                else
                {
                    parser.NextToken();
                }

                // get the parameters
                while (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                {
                    parser.NextToken();
                    string errMsg;
                    if (!defNode.AddArgument(parser.Token, out errMsg))
                    {
                        parser.ReportSyntaxError(errMsg);
                    }
                    if (parser.PeekToken(TokenKind.Comma))
                    {
                        parser.NextToken();
                    }

                    // TODO: probably need to handle "end" "function" case...won't right now
                }

                if (!parser.PeekToken(TokenKind.RightParenthesis))
                {
                    parser.ReportSyntaxError("A report must specify zero or more parameters in the form: ([param1][,...])");
                }
                else
                {
                    parser.NextToken();
                }

                List <List <TokenKind> > breakSequences =
                    new List <List <TokenKind> >(Genero4glAst.ValidStatementKeywords
                                                 .Where(x => x != TokenKind.EndKeyword && x != TokenKind.ReportKeyword)
                                                 .Select(x => new List <TokenKind> {
                    x
                }))
                {
                    new List <TokenKind> {
                        TokenKind.EndKeyword, TokenKind.ReportKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.OutputKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.OrderKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.FormatKeyword
                    }
                };

                while (!parser.PeekToken(TokenKind.EndOfFile) &&
                       !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ReportKeyword, 2)))
                {
                    DefineNode      defineNode;
                    TypeDefNode     typeNode;
                    ConstantDefNode constNode;
                    bool            matchedBreakSequence = false;
                    bool            inDefSection         = true;
                    switch (parser.PeekToken().Kind)
                    {
                    case TokenKind.TypeKeyword:
                    {
                        if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null)
                        {
                            defNode.Children.Add(typeNode.StartIndex, typeNode);
                            foreach (var def in typeNode.GetDefinitions())
                            {
                                def.Scope = "local type";
                                if (!defNode.Types.ContainsKey(def.Name))
                                {
                                    defNode.Types.Add(def.Name, def);
                                }
                                else
                                {
                                    parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Type {0} defined more than once.", def.Name), Severity.Error);
                                }
                            }
                        }
                        break;
                    }

                    case TokenKind.ConstantKeyword:
                    {
                        if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null)
                        {
                            defNode.Children.Add(constNode.StartIndex, constNode);
                            foreach (var def in constNode.GetDefinitions())
                            {
                                def.Scope = "local constant";
                                if (!defNode.Constants.ContainsKey(def.Name))
                                {
                                    defNode.Constants.Add(def.Name, def);
                                }
                                else
                                {
                                    parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Constant {0} defined more than once.", def.Name), Severity.Error);
                                }
                            }
                        }
                        break;
                    }

                    case TokenKind.DefineKeyword:
                    {
                        if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences, defNode.BindArgument) && defineNode != null)
                        {
                            defNode.Children.Add(defineNode.StartIndex, defineNode);
                            foreach (var def in defineNode.GetDefinitions())
                            {
                                foreach (var vardef in def.VariableDefinitions)
                                {
                                    vardef.Scope = "local variable";
                                    if (!defNode.Variables.ContainsKey(vardef.Name))
                                    {
                                        defNode.Variables.Add(vardef.Name, vardef);
                                    }
                                    else
                                    {
                                        parser.ReportSyntaxError(vardef.LocationIndex, vardef.LocationIndex + vardef.Name.Length, string.Format("Variable {0} defined more than once.", vardef.Name), Severity.Error);
                                    }
                                }
                            }
                        }
                        break;
                    }

                    default:
                        inDefSection = false;
                        break;
                    }

                    if (!inDefSection)
                    {
                        break;
                    }
                }

                if (parser.PeekToken(TokenKind.OutputKeyword))
                {
                    parser.NextToken();
                    bool           isValid = true;
                    ExpressionNode expr;
                    while (isValid)
                    {
                        if (parser.PeekToken(TokenKind.ReportKeyword))
                        {
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.ToKeyword))
                            {
                                parser.NextToken();
                                switch (parser.PeekToken().Kind)
                                {
                                case TokenKind.ScreenKeyword:
                                case TokenKind.PrinterKeyword:
                                    parser.NextToken();
                                    break;

                                case TokenKind.FileKeyword:
                                    parser.NextToken();
                                    if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                    {
                                        defNode.OutputFilename = expr;
                                    }
                                    else
                                    {
                                        parser.ReportSyntaxError("Invalid filename found in report.");
                                    }
                                    break;

                                case TokenKind.PipeKeyword:
                                    parser.NextToken();
                                    if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                    {
                                        defNode.OutputProgram = expr;
                                    }
                                    else
                                    {
                                        parser.ReportSyntaxError("Invalid program name found in report.");
                                    }
                                    if (parser.PeekToken(TokenKind.InKeyword))
                                    {
                                        parser.NextToken();
                                        if ((parser.PeekToken(TokenKind.FormKeyword) || parser.PeekToken(TokenKind.LineKeyword)) &&
                                            parser.PeekToken(TokenKind.ModeKeyword, 2))
                                        {
                                            parser.NextToken();
                                            parser.NextToken();
                                        }
                                        else
                                        {
                                            parser.ReportSyntaxError("Expected \"form mode\" or \"line mode\" in report.");
                                        }
                                    }
                                    break;

                                default:
                                    if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                    {
                                        defNode.OutputFilename = expr;
                                    }
                                    else
                                    {
                                        parser.ReportSyntaxError("Invalid filename found in report.");
                                    }
                                    break;
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"to\" keyword in report.");
                            }
                        }

                        switch (parser.PeekToken().Kind)
                        {
                        case TokenKind.WithKeyword:
                            parser.NextToken();
                            break;

                        case TokenKind.LeftKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.MarginKeyword))
                            {
                                parser.NextToken();
                                if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                {
                                    defNode.MarginLeft = expr;
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Invalid margin value found in report.");
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"margin\" keyword in report.");
                            }
                            break;

                        case TokenKind.RightKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.MarginKeyword))
                            {
                                parser.NextToken();
                                if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                {
                                    defNode.MarginRight = expr;
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Invalid margin value found in report.");
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"margin\" keyword in report.");
                            }
                            break;

                        case TokenKind.BottomKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.MarginKeyword))
                            {
                                parser.NextToken();
                                if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                {
                                    defNode.MarginBottom = expr;
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Invalid margin value found in report.");
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"margin\" keyword in report.");
                            }
                            break;

                        case TokenKind.PageKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.LengthKeyword))
                            {
                                parser.NextToken();
                                if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                {
                                    defNode.PageLength = expr;
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Invalid page length value found in report.");
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"length\" keyword in report.");
                            }
                            break;

                        case TokenKind.TopKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.OfKeyword) && parser.PeekToken(TokenKind.PageKeyword, 2))
                            {
                                parser.NextToken();
                                parser.NextToken();
                                if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                {
                                    defNode.TopOfPage = expr;
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Invalid top of page value found in report.");
                                }
                            }
                            else if (parser.PeekToken(TokenKind.MarginKeyword))
                            {
                                parser.NextToken();
                                if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                                {
                                    defNode.MarginTop = expr;
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Invalid margin value found in report.");
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Invalid token found in report.");
                            }
                            break;

                        default:
                            isValid = false;
                            parser.ReportSyntaxError("Invalid token found in output section of report.");
                            break;
                        }

                        if (parser.PeekToken(TokenKind.OrderKeyword) ||
                            parser.PeekToken(TokenKind.FormatKeyword) ||
                            parser.PeekToken(TokenKind.EndOfFile) ||
                            (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ReportKeyword, 2)))
                        {
                            break;
                        }
                    }
                }

                if (parser.PeekToken(TokenKind.OrderKeyword))
                {
                    parser.NextToken();
                    if (parser.PeekToken(TokenKind.ExternalKeyword))
                    {
                        parser.NextToken();
                    }
                    if (parser.PeekToken(TokenKind.ByKeyword))
                    {
                        parser.NextToken();
                    }
                    else
                    {
                        parser.ReportSyntaxError("Expected \"by\" keyword in order section of report.");
                    }

                    // collect report variables
                    FglNameExpression varName;
                    while (FglNameExpression.TryParseNode(parser, out varName))
                    {
                        defNode.OrderVarNames.Add(varName);
                        if (parser.PeekToken(TokenKind.AscKeyword) || parser.PeekToken(TokenKind.DescKeyword))
                        {
                            parser.NextToken();
                        }
                        if (parser.PeekToken(TokenKind.Comma))
                        {
                            parser.NextToken();
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                List <TokenKind> validExits = new List <TokenKind> {
                    TokenKind.ProgramKeyword, TokenKind.ReportKeyword
                };

                ReportFormatSection rfs;
                while (ReportFormatSection.TryParseNode(parser, out rfs, containingModule, defNode, null, defNode.StoreReturnStatement,
                                                        defNode.AddLimitedScopeVariable, validExits) && rfs != null)
                {
                    defNode.Children.Add(rfs.StartIndex, rfs);
                    if (parser.PeekToken(TokenKind.EndOfFile) ||
                        (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ReportKeyword, 2)))
                    {
                        break;
                    }
                }

                if (!parser.PeekToken(TokenKind.EndOfFile))
                {
                    parser.NextToken();
                    if (parser.PeekToken(TokenKind.ReportKeyword))
                    {
                        parser.NextToken();
                        defNode.EndIndex   = parser.Token.Span.End;
                        defNode.IsComplete = true;
                        defNode.AddLimitedScopeVariable(Genero4glAst.PagenoVariable, defNode.StartIndex, defNode.EndIndex);
                    }
                    else
                    {
                        parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of report definition.");
                    }
                }
                else
                {
                    parser.ReportSyntaxError("Unexpected end of report definition");
                }
            }
            return(result);
        }
Esempio n. 2
0
        public static bool TryParseNode(Genero4glParser parser, out ReportFormatSection node,
                                        IModuleResult containingModule,
                                        ReportBlockNode reportNode,
                                        Action <PrepareStatement> prepStatementBinder = null,
                                        Func <ReturnStatement, ParserResult> returnStatementBinder   = null,
                                        Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null,
                                        List <TokenKind> validExitKeywords = null,
                                        IEnumerable <ContextStatementFactory> contextStatementFactories = null)
        {
            node = null;
            bool result = false;

            if (parser.PeekToken(TokenKind.FormatKeyword))
            {
                parser.NextToken();
                result          = true;
                node            = new ReportFormatSection();
                node.StartIndex = parser.Token.Span.Start;

                bool isValid = true;
                while (isValid)
                {
                    if (parser.PeekToken(TokenKind.EveryKeyword) && parser.PeekToken(TokenKind.RowKeyword, 2))
                    {
                        parser.NextToken();
                        parser.NextToken();
                        node._canOutline = false;
                    }
                    else
                    {
                        node._canOutline = true;
                        switch (parser.PeekToken().Kind)
                        {
                        case TokenKind.FirstKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.PageKeyword) && parser.PeekToken(TokenKind.HeaderKeyword, 2))
                            {
                                parser.NextToken();
                                parser.NextToken();
                                if (node.DecoratorEnd == 0)
                                {
                                    node.DecoratorEnd = parser.Token.Span.End;
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"page header\" in format section of report.");
                            }
                            break;

                        case TokenKind.PageKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.HeaderKeyword))
                            {
                                parser.NextToken();
                                if (node.DecoratorEnd == 0)
                                {
                                    node.DecoratorEnd = parser.Token.Span.End;
                                }
                            }
                            else if (parser.PeekToken(TokenKind.TrailerKeyword))
                            {
                                parser.NextToken();
                                if (node.DecoratorEnd == 0)
                                {
                                    node.DecoratorEnd = parser.Token.Span.End;
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"header\" or \"trailer\" in format section of report.");
                            }
                            break;

                        case TokenKind.OnKeyword:
                            parser.NextToken();
                            if ((parser.PeekToken(TokenKind.EveryKeyword) || parser.PeekToken(TokenKind.LastKeyword)) &&
                                parser.PeekToken(TokenKind.RowKeyword, 2))
                            {
                                parser.NextToken();
                                parser.NextToken();
                                if (node.DecoratorEnd == 0)
                                {
                                    node.DecoratorEnd = parser.Token.Span.End;
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"every row\" or \"last row\" in format section of report.");
                            }
                            break;

                        case TokenKind.BeforeKeyword:
                        case TokenKind.AfterKeyword:
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.GroupKeyword) &&
                                parser.PeekToken(TokenKind.OfKeyword, 2))
                            {
                                parser.NextToken();
                                parser.NextToken();
                                // TODO: get report variable
                                FglNameExpression name;
                                if (FglNameExpression.TryParseNode(parser, out name))
                                {
                                    node.ReportVariable = name;
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Invalid name expression found in format section of report.");
                                }
                                if (node.DecoratorEnd == 0)
                                {
                                    node.DecoratorEnd = parser.Token.Span.End;
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected \"group of\" in format section of report.");
                            }
                            break;

                        default:
                            isValid = false;
                            break;
                        }

                        if (isValid)
                        {
                            // collect statements
                            FglStatement rptStmt;
                            while (ReportStatementFactory.TryGetStatement(parser, out rptStmt, containingModule, reportNode, new List <Func <PrepareStatement, bool> >(), returnStatementBinder,
                                                                          limitedScopeVariableAdder, validExitKeywords) && rptStmt != null)
                            {
                                if (rptStmt.StartIndex < 0)
                                {
                                    continue;
                                }
                                node.Children.Add(rptStmt.StartIndex, rptStmt);
                            }
                        }
                    }
                    node.EndIndex = parser.Token.Span.End;
                }
            }

            return(result);
        }