Example #1
0
        public static bool TryGetStatement(Genero4glParser parser, out FglStatement node,
                                           IModuleResult containingModule,
                                           ReportBlockNode reportNode,
                                           List <Func <PrepareStatement, bool> > prepStatementBinders,
                                           Func <ReturnStatement, ParserResult> returnStatementBinder   = null,
                                           Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null,
                                           List <TokenKind> validExitKeywords = null,
                                           IEnumerable <ContextStatementFactory> contextStatementFactories = null)
        {
            bool result = false;

            node = null;

            if (!(result = TryGetReportStatement(parser, out node, reportNode)))
            {
                List <ContextStatementFactory> csfs = new List <ContextStatementFactory>();
                if (contextStatementFactories != null)
                {
                    csfs.AddRange(contextStatementFactories);
                }
                csfs.Add((x) =>
                {
                    FglStatement testNode;
                    TryGetReportStatement(x, out testNode, reportNode, true);
                    return(testNode);
                });
                result = parser.StatementFactory.TryParseNode(parser, out node, containingModule, prepStatementBinders, returnStatementBinder,
                                                              limitedScopeVariableAdder, false, validExitKeywords, csfs,
                                                              new ExpressionParsingOptions
                {
                    AllowStarParam = true,
                    AdditionalExpressionParsers = new ExpressionParser[] { (x) => ParseAggregateReportFunction(x, reportNode) }
                });
            }

            return(result);
        }
Example #2
0
        public static bool TryParseNode(IParser parser, out PrintStatement node, ReportBlockNode reportNode)
        {
            node = null;
            bool result = false;

            if (parser.PeekToken(TokenKind.PrintKeyword))
            {
                result = true;
                node   = new PrintStatement();
                parser.NextToken();
                node.StartIndex        = parser.Token.Span.Start;
                node.WhereExpressions  = new List <ExpressionNode>();
                node.ColumnExpressions = new List <ExpressionNode>();
                node.VariableNames     = new List <ExpressionNode>();
                node.Filenames         = new List <ExpressionNode>();
                node.OtherExpressions  = new List <ExpressionNode>();

                TokenKind nextTokKind = parser.PeekToken().Kind;

                if (ReportStatementFactory.StatementStartKeywords.Contains(nextTokKind) ||
                    Genero4glAst.ValidStatementKeywords.Contains(nextTokKind) ||
                    parser.PeekToken(TokenKind.OnKeyword) ||
                    parser.PeekToken(TokenKind.EveryKeyword) ||
                    (parser.PeekToken(TokenKind.FirstKeyword) && parser.PeekToken(TokenKind.PageKeyword, 2)) ||
                    parser.PeekToken(TokenKind.PageKeyword) ||
                    parser.PeekToken(TokenKind.BeforeKeyword) ||
                    parser.PeekToken(TokenKind.AfterKeyword))
                {
                    node.EndIndex = parser.Token.Span.End;
                    return(true);
                }


                List <TokenKind> breaks = new List <TokenKind> {
                    TokenKind.Comma
                };
                while (true)
                {
                    if (parser.PeekToken(TokenKind.GroupKeyword))
                    {
                        parser.NextToken();
                    }

                    switch (parser.PeekToken().Kind)
                    {
                    case TokenKind.PagenoKeyword:
                    case TokenKind.LinenoKeyword:
                        parser.NextToken();
                        if (parser.PeekToken(TokenKind.UsingKeyword))
                        {
                            parser.NextToken();
                            if (parser.PeekToken(TokenCategory.StringLiteral))
                            {
                                parser.NextToken();
                            }
                            if (parser.PeekToken(TokenKind.ClippedKeyword))
                            {
                                parser.NextToken();
                            }
                        }
                        break;

                    case TokenKind.ColumnKeyword:
                    {
                        parser.NextToken();
                        ExpressionNode colExpr;
                        if (FglExpressionNode.TryGetExpressionNode(parser, out colExpr, breaks))
                        {
                            node.ColumnExpressions.Add(colExpr);
                        }
                        break;
                    }

                    case TokenKind.CountKeyword:
                    case TokenKind.PercentKeyword:
                    {
                        parser.NextToken();
                        if (parser.PeekToken(TokenKind.LeftParenthesis))
                        {
                            parser.NextToken();
                            if (parser.PeekToken(TokenKind.Multiply))
                            {
                                parser.NextToken();
                                if (parser.PeekToken(TokenKind.RightParenthesis))
                                {
                                    parser.NextToken();
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Expected right-paren in print statement.");
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Expected '*' in print statement.");
                            }
                        }
                        else
                        {
                            parser.ReportSyntaxError("Expected left-paren in print statement.");
                        }

                        if (parser.PeekToken(TokenKind.WhereKeyword))
                        {
                            parser.NextToken();
                            ExpressionNode whereClause;
                            if (FglExpressionNode.TryGetExpressionNode(parser, out whereClause, breaks))
                            {
                                node.WhereExpressions.Add(whereClause);
                            }
                        }

                        if (parser.PeekToken(TokenKind.UsingKeyword))
                        {
                            parser.NextToken();
                            if (parser.PeekToken(TokenCategory.StringLiteral))
                            {
                                parser.NextToken();
                            }
                            if (parser.PeekToken(TokenKind.ClippedKeyword))
                            {
                                parser.NextToken();
                            }
                        }
                        break;
                    }

                    case TokenKind.SumKeyword:
                    case TokenKind.MinKeyword:
                    case TokenKind.MaxKeyword:
                    case TokenKind.AvgKeyword:
                    {
                        parser.NextToken();
                        if (parser.PeekToken(TokenKind.LeftParenthesis))
                        {
                            parser.NextToken();
                            ExpressionNode varName;
                            if (FglExpressionNode.TryGetExpressionNode(parser, out varName))
                            {
                                node.VariableNames.Add(varName);
                                if (parser.PeekToken(TokenKind.RightParenthesis))
                                {
                                    parser.NextToken();
                                }
                                else
                                {
                                    parser.ReportSyntaxError("Expected right-paren in print statement.");
                                }
                            }
                            else
                            {
                                parser.ReportSyntaxError("Invalid variable name found in print statement.");
                            }
                        }
                        else
                        {
                            parser.ReportSyntaxError("Expected left-paren in print statement.");
                        }

                        if (parser.PeekToken(TokenKind.WhereKeyword))
                        {
                            parser.NextToken();
                            ExpressionNode whereClause;
                            if (FglExpressionNode.TryGetExpressionNode(parser, out whereClause, breaks))
                            {
                                node.WhereExpressions.Add(whereClause);
                            }
                        }

                        if (parser.PeekToken(TokenKind.UsingKeyword))
                        {
                            parser.NextToken();
                            if (parser.PeekToken(TokenCategory.StringLiteral))
                            {
                                parser.NextToken();
                            }
                            if (parser.PeekToken(TokenKind.ClippedKeyword))
                            {
                                parser.NextToken();
                            }
                        }
                        break;
                    }

                    case TokenKind.FileKeyword:
                    {
                        parser.NextToken();
                        ExpressionNode filename;
                        if (FglExpressionNode.TryGetExpressionNode(parser, out filename, breaks))
                        {
                            node.Filenames.Add(filename);
                        }
                        break;
                    }

                    default:
                    {
                        ExpressionNode expr;
                        if (FglExpressionNode.TryGetExpressionNode(parser, out expr, breaks, new ExpressionParsingOptions
                            {
                                AllowStarParam = true,
                                AdditionalExpressionParsers = new ExpressionParser[] { (x) => ReportStatementFactory.ParseAggregateReportFunction(x, reportNode) }
                            }))
                        {
                            node.OtherExpressions.Add(expr);
                            if (parser.PeekToken(TokenKind.SpacesKeyword))
                            {
                                parser.NextToken();
                            }
                            else if (parser.PeekToken(TokenKind.WordwrapKeyword))
                            {
                                parser.NextToken();
                                if (parser.PeekToken(TokenKind.RightKeyword) && parser.PeekToken(TokenKind.MarginKeyword, 2))
                                {
                                    parser.NextToken();
                                    parser.NextToken();
                                    if (FglExpressionNode.TryGetExpressionNode(parser, out expr, breaks))
                                    {
                                        node.OtherExpressions.Add(expr);
                                    }
                                    else
                                    {
                                        parser.ReportSyntaxError("Invalid expression found in print statement.");
                                    }
                                }
                            }
                        }
                        break;
                    }
                    }

                    var tokKind = parser.PeekToken().Kind;
                    if (tokKind == TokenKind.Comma)
                    {
                        parser.NextToken();
                    }
                    else if (tokKind == TokenKind.Semicolon)
                    {
                        parser.NextToken();
                        break;
                    }
                    else if (tokKind >= TokenKind.FirstOperator &&
                             tokKind <= TokenKind.LastOperator)
                    {
                        parser.NextToken();
                    }
                    else
                    {
                        break;
                    }
                }

                node.EndIndex = parser.Token.Span.End;
            }

            return(result);
        }
Example #3
0
        public static bool TryParseNode(Genero4glParser parser, out ModuleNode defNode)
        {
            defNode = new ModuleNode();
            if (!string.IsNullOrWhiteSpace(parser.Filename))
            {
                defNode.ProgramName = Path.GetFileName(Path.GetDirectoryName(parser.Filename));
            }

            NodesProcessed processed = NodesProcessed.None;

            while (!parser.PeekToken(TokenKind.EndOfFile))
            {
                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                CompilerOptionsNode compOptionsNode;
                if (CompilerOptionsNode.TryParseNode(parser, out compOptionsNode) && compOptionsNode != null)
                {
                    if (processed == NodesProcessed.None)
                    {
                        defNode.Children.Add(compOptionsNode.StartIndex, compOptionsNode);
                    }
                    else
                    {
                        parser.ReportSyntaxError("Compiler options statement found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.None)
                {
                    processed = NodesProcessed.CompilerOption;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                ImportModuleNode importNode;
                if (ImportModuleNode.TryParseNode(parser, out importNode) && importNode != null)
                {
                    if (processed == NodesProcessed.CompilerOption)
                    {
                        if (!defNode.Children.ContainsKey(importNode.StartIndex))
                        {
                            defNode.Children.Add(importNode.StartIndex, importNode);
                            if (!string.IsNullOrWhiteSpace(importNode.ImportName))
                            {
                                if (importNode.ImportType == ImportModuleType.C)
                                {
                                    defNode.CExtensionImports.Add(importNode.ImportName);
                                }
                                else if (importNode.ImportType == ImportModuleType.Java)
                                {
                                    defNode.JavaImports.Add(importNode.ImportName);
                                }
                                else
                                {
                                    defNode.FglImports.Add(importNode.ImportName);
                                }
                            }
                        }
                        continue;
                    }
                    else
                    {
                        parser.ReportSyntaxError("Import statement found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.CompilerOption)
                {
                    processed = NodesProcessed.Imports;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                SchemaSpecificationNode schemaNode;
                if (SchemaSpecificationNode.TryParseDefine(parser, out schemaNode) && schemaNode != null)
                {
                    if (processed == NodesProcessed.Imports)
                    {
                        if (!defNode.Children.ContainsKey(schemaNode.StartIndex))
                        {
                            defNode.Children.Add(schemaNode.StartIndex, schemaNode);
                        }
                    }
                    else
                    {
                        parser.ReportSyntaxError("Schema statement found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.Imports)
                {
                    processed = NodesProcessed.SchemaSpec;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                GlobalsNode globalNode;
                if (GlobalsNode.TryParseNode(parser, out globalNode) && globalNode != null)
                {
                    if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions)
                    {
                        defNode.Children.Add(globalNode.StartIndex, globalNode);
                        foreach (var cGlobKVP in globalNode.Constants)
                        {
                            if (!defNode.GlobalConstants.ContainsKey(cGlobKVP.Key))
                            {
                                defNode.GlobalConstants.Add(cGlobKVP);
                            }
                            else
                            {
                                parser.ReportSyntaxError(cGlobKVP.Value.LocationIndex, cGlobKVP.Value.LocationIndex + cGlobKVP.Value.Name.Length, string.Format("Global constant {0} defined more than once.", cGlobKVP.Key), Severity.Error);
                            }
                        }
                        foreach (var tGlobKVP in globalNode.Types)
                        {
                            if (!defNode.GlobalTypes.ContainsKey(tGlobKVP.Key))
                            {
                                defNode.GlobalTypes.Add(tGlobKVP);
                            }
                            else
                            {
                                parser.ReportSyntaxError(tGlobKVP.Value.LocationIndex, tGlobKVP.Value.LocationIndex + tGlobKVP.Value.Name.Length, string.Format("Global type {0} defined more than once.", tGlobKVP.Key), Severity.Error);
                            }
                        }
                        foreach (var vGlobKVP in globalNode.Variables)
                        {
                            if (!defNode.GlobalVariables.ContainsKey(vGlobKVP.Key))
                            {
                                defNode.GlobalVariables.Add(vGlobKVP);
                            }
                            else
                            {
                                parser.ReportSyntaxError(vGlobKVP.Value.LocationIndex, vGlobKVP.Value.LocationIndex + vGlobKVP.Value.Name.Length, string.Format("Global variable {0} defined more than once.", vGlobKVP.Key), Severity.Error);
                            }
                        }
                        continue;
                    }
                    else
                    {
                        parser.ReportSyntaxError("Globals statement found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.SchemaSpec)
                {
                    processed = NodesProcessed.MemberDefinitions;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                bool                     matchedBreakSequence = false;
                ConstantDefNode          constNode;
                List <List <TokenKind> > breakSequences = new List <List <TokenKind> >()
                {
                    new List <TokenKind> {
                        TokenKind.GlobalsKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.PublicKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.PrivateKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.ConstantKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.DefineKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.TypeKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.FunctionKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.MainKeyword
                    },
                    new List <TokenKind> {
                        TokenKind.ReportKeyword
                    }
                };
                if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null)
                {
                    if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions)
                    {
                        defNode.Children.Add(constNode.StartIndex, constNode);
                        foreach (var def in constNode.GetDefinitions())
                        {
                            def.Scope = "module 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("Module constant {0} defined more than once.", def.Name), Severity.Error);
                            }
                        }
                        continue;
                    }
                    else
                    {
                        parser.ReportSyntaxError("Constant definition found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.SchemaSpec)
                {
                    processed = NodesProcessed.MemberDefinitions;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                TypeDefNode typeNode;
                if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null)
                {
                    if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions)
                    {
                        if (!defNode.Children.ContainsKey(typeNode.StartIndex))
                        {
                            defNode.Children.Add(typeNode.StartIndex, typeNode);
                        }
                        foreach (var def in typeNode.GetDefinitions())
                        {
                            def.Scope = "module 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("Module type {0} defined more than once.", def.Name), Severity.Error);
                            }
                        }
                        continue;
                    }
                    else
                    {
                        parser.ReportSyntaxError("Type definition found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.SchemaSpec)
                {
                    processed = NodesProcessed.MemberDefinitions;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                DefineNode defineNode;
                if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences) && defineNode != null)
                {
                    if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions)
                    {
                        defNode.Children.Add(defineNode.StartIndex, defineNode);
                        foreach (var def in defineNode.GetDefinitions())
                        {
                            foreach (var vardef in def.VariableDefinitions)
                            {
                                vardef.Scope = "module variable";
                                vardef.SetIsPublic(defineNode.AccessModifier == AccessModifier.Public);
                                if (!defNode.Variables.ContainsKey(vardef.Name))
                                {
                                    defNode.Variables.Add(vardef.Name, vardef);
                                }
                                else
                                {
                                    parser.ReportSyntaxError(vardef.LocationIndex, vardef.LocationIndex + vardef.Name.Length, string.Format("Module variable {0} defined more than once.", vardef.Name), Severity.Error);
                                }
                            }
                        }
                        continue;
                    }
                    else
                    {
                        parser.ReportSyntaxError("Variable definition found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.SchemaSpec)
                {
                    processed = NodesProcessed.MemberDefinitions;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                MainBlockNode mainBlock;
                if (MainBlockNode.TryParseNode(parser, out mainBlock, defNode) && mainBlock != null)
                {
                    if (processed == NodesProcessed.MemberDefinitions)
                    {
                        defNode.Children.Add(mainBlock.StartIndex, mainBlock);
                        defNode.Functions.Add(mainBlock.Name, mainBlock);
                        foreach (var cursor in mainBlock.Children.Values.Where(x => x is PrepareStatement || x is DeclareStatement))
                        {
                            IAnalysisResult curRes = cursor as IAnalysisResult;
                            if (!defNode.Cursors.ContainsKey(curRes.Name))
                            {
                                defNode.Cursors.Add(curRes.Name, curRes);
                            }
                        }
                    }
                    else
                    {
                        parser.ReportSyntaxError("Main block found in incorrect position.");
                    }
                }
                if (processed == NodesProcessed.MemberDefinitions)
                {
                    processed = NodesProcessed.Main;
                }

                if (CheckForPreprocessorNode(parser, defNode))
                {
                    continue;
                }

                FunctionBlockNode      funcNode;
                ReportBlockNode        repNode;
                DeclarativeDialogBlock dialogNode;
                int dummy;
                if (FunctionBlockNode.TryParseNode(parser, out funcNode, out dummy, defNode) && funcNode != null)
                {
                    defNode.Children.Add(funcNode.StartIndex, funcNode);
                    funcNode.Scope = "function";

                    if (string.IsNullOrWhiteSpace(funcNode.Name))
                    {
                        parser.ReportSyntaxError(funcNode.LocationIndex, funcNode.LocationIndex, "Invalid function definition found.");
                    }
                    else if (!defNode.Functions.ContainsKey(funcNode.Name))
                    {
                        defNode.Functions.Add(funcNode.Name, funcNode);
                    }
                    else
                    {
                        parser.ReportSyntaxError(funcNode.LocationIndex, funcNode.LocationIndex + funcNode.Name.Length, string.Format("Function {0} defined more than once.", funcNode.Name), Severity.Error);
                    }
                }
                else if (ReportBlockNode.TryParseNode(parser, out repNode, defNode) && repNode != null)
                {
                    defNode.Children.Add(repNode.StartIndex, repNode);

                    repNode.Scope = "report";
                    if (string.IsNullOrWhiteSpace(repNode.Name))
                    {
                        parser.ReportSyntaxError(repNode.LocationIndex, repNode.LocationIndex, "Invalid report definition found.");
                    }
                    else if (!defNode.Functions.ContainsKey(repNode.Name))
                    {
                        defNode.Functions.Add(repNode.Name, repNode);
                    }
                    else
                    {
                        parser.ReportSyntaxError(repNode.LocationIndex, repNode.LocationIndex + repNode.Name.Length, string.Format("Report {0} defined more than once.", repNode.Name), Severity.Error);
                    }
                }
                else if (DeclarativeDialogBlock.TryParseNode(parser, out dialogNode, defNode) && dialogNode != null)
                {
                    defNode.Children.Add(dialogNode.StartIndex, dialogNode);
                    dialogNode.Scope = "dialog";
                    if (string.IsNullOrWhiteSpace(dialogNode.Name))
                    {
                        parser.ReportSyntaxError(dialogNode.LocationIndex, dialogNode.LocationIndex, "Invalid declarative dialog definition found.");
                    }
                    else if (!defNode.Functions.ContainsKey(dialogNode.Name))
                    {
                        defNode.Functions.Add(dialogNode.Name, dialogNode);
                    }
                    else
                    {
                        parser.ReportSyntaxError(dialogNode.LocationIndex, dialogNode.LocationIndex + dialogNode.Name.Length, string.Format("Declarative dialog {0} defined more than once.", dialogNode.Name), Severity.Error);
                    }
                }
                else
                {
                    parser.NextToken();
                }
            }

            if (defNode.Children.Count > 0)
            {
                defNode.StartIndex = defNode.Children[defNode.Children.Keys[0]].StartIndex;
                defNode.EndIndex   = defNode.Children[defNode.Children.Keys[defNode.Children.Count - 1]].EndIndex;
                defNode.IsComplete = true;
            }

            return(true);
        }
Example #4
0
        internal static ExpressionNode ParseAggregateReportFunction(IParser parser, ReportBlockNode reportNode)
        {
            ExpressionNode node = null;

            if (reportNode != null)
            {
                var tokStr = parser.PeekToken().Value.ToString();
                if (reportNode.Variables.ContainsKey(tokStr))
                {
                    switch (tokStr.ToLower())
                    {
                    case "group":
                    {
                        var nextTokKind = parser.PeekToken(2).Kind;
                        if (nextTokKind != TokenKind.CountKeyword &&
                            nextTokKind != TokenKind.PercentKeyword &&
                            nextTokKind != TokenKind.SumKeyword &&
                            nextTokKind != TokenKind.AvgKeyword &&
                            nextTokKind != TokenKind.MinKeyword &&
                            nextTokKind != TokenKind.MaxKeyword)
                        {
                            return(null);
                        }
                        break;
                    }

                    case "count":
                    case "percent":
                    case "sum":
                    case "avg":
                    case "min":
                    case "max":
                    {
                        if (!parser.PeekToken(TokenKind.LeftParenthesis, 2))
                        {
                            return(null);
                        }
                        break;
                    }
                    }
                }
            }

            if (parser.PeekToken(TokenKind.GroupKeyword))
            {
                parser.NextToken();
                node = new TokenExpressionNode(parser.Token);
            }

            switch (parser.PeekToken().Kind)
            {
            case TokenKind.CountKeyword:
            case TokenKind.PercentKeyword:
            {
                parser.NextToken();
                if (node == null)
                {
                    node = new TokenExpressionNode(parser.Token);
                }
                else
                {
                    node.AppendExpression(new TokenExpressionNode(parser.Token));
                }
                if (parser.PeekToken(TokenKind.LeftParenthesis))
                {
                    parser.NextToken();
                    node.AppendExpression(new TokenExpressionNode(parser.Token));
                    if (parser.PeekToken(TokenKind.Multiply))
                    {
                        parser.NextToken();
                        node.AppendExpression(new TokenExpressionNode(parser.Token));
                        if (parser.PeekToken(TokenKind.RightParenthesis))
                        {
                            parser.NextToken();
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                        }
                        else
                        {
                            parser.ReportSyntaxError("Expected right-paren in report aggregate function.");
                        }
                    }
                    else
                    {
                        parser.ReportSyntaxError("Expected '*' in report aggregate function.");
                    }
                }
                else
                {
                    parser.ReportSyntaxError("Expected left-paren in report aggregate function.");
                }

                // get the optional where clause
                if (parser.PeekToken(TokenKind.WhereKeyword))
                {
                    parser.NextToken();
                    node.AppendExpression(new TokenExpressionNode(parser.Token));
                    ExpressionNode whereExpr;
                    if (FglExpressionNode.TryGetExpressionNode(parser, out whereExpr))
                    {
                        node.AppendExpression(whereExpr);
                    }
                    else
                    {
                        parser.ReportSyntaxError("Invalid expression in report aggregate function.");
                    }
                }
                break;
            }

            case TokenKind.SumKeyword:
            case TokenKind.AvgKeyword:
            case TokenKind.MinKeyword:
            case TokenKind.MaxKeyword:
            {
                parser.NextToken();
                if (node == null)
                {
                    node = new TokenExpressionNode(parser.Token);
                }
                if (parser.PeekToken(TokenKind.LeftParenthesis))
                {
                    parser.NextToken();
                    node.AppendExpression(new TokenExpressionNode(parser.Token));
                    ExpressionNode expr;
                    if (FglExpressionNode.TryGetExpressionNode(parser, out expr))
                    {
                        node.AppendExpression(expr);
                        if (parser.PeekToken(TokenKind.RightParenthesis))
                        {
                            parser.NextToken();
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                        }
                        else
                        {
                            parser.ReportSyntaxError("Expected right-paren in report aggregate function.");
                        }
                    }
                    else
                    {
                        parser.ReportSyntaxError("Invalid expression in report aggregate function.");
                    }
                }
                else
                {
                    parser.ReportSyntaxError("Expected left-paren in report aggregate function.");
                }

                // get the optional where clause
                if (parser.PeekToken(TokenKind.WhereKeyword))
                {
                    parser.NextToken();
                    node.AppendExpression(new TokenExpressionNode(parser.Token));
                    ExpressionNode whereExpr;
                    if (FglExpressionNode.TryGetExpressionNode(parser, out whereExpr))
                    {
                        node.AppendExpression(whereExpr);
                    }
                    else
                    {
                        parser.ReportSyntaxError("Invalid expression in report aggregate function.");
                    }
                }
                break;
            }
            }

            return(node);
        }
Example #5
0
        private static bool TryGetReportStatement(IParser parser, out FglStatement node, ReportBlockNode reportNode, bool returnFalseInsteadOfErrors = false)
        {
            bool result = false;

            node = null;

            switch (parser.PeekToken().Kind)
            {
            case TokenKind.PrintKeyword:
            {
                PrintStatement prtStmt;
                if ((result = PrintStatement.TryParseNode(parser, out prtStmt, reportNode)))
                {
                    node = prtStmt;
                }
                break;
            }

            case TokenKind.PrintxKeyword:
            {
                PrintxStatement prtxStmt;
                if ((result = PrintxStatement.TryParseNode(parser, out prtxStmt)))
                {
                    node = prtxStmt;
                }
                break;
            }

            case TokenKind.NeedKeyword:
            {
                NeedStatement needStmt;
                if ((result = NeedStatement.TryParseNode(parser, out needStmt)))
                {
                    node = needStmt;
                }
                break;
            }

            case TokenKind.PauseKeyword:
            {
                PauseStatement pauseStmt;
                if ((result = PauseStatement.TryParseNode(parser, out pauseStmt)))
                {
                    node = pauseStmt;
                }
                break;
            }

            case TokenKind.SkipKeyword:
            {
                SkipStatement skipStmt;
                if ((result = SkipStatement.TryParseNode(parser, out skipStmt)))
                {
                    node = skipStmt;
                }
                break;
            }

            default:
                result = false;
                break;
            }

            return(result);
        }
Example #6
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);
        }
Example #7
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);
        }