public virtual RuleAST ParseArtificialRule(Grammar g, string ruleText)
        {
            ANTLRLexer        lexer   = new ANTLRLexer(new ANTLRStringStream(ruleText));
            GrammarASTAdaptor adaptor = new GrammarASTAdaptor(lexer.CharStream);
            CommonTokenStream tokens  = new CommonTokenStream(lexer);

            lexer.tokens = tokens;
            ToolANTLRParser p = new ToolANTLRParser(tokens, tool);

            p.TreeAdaptor = adaptor;
            IToken ruleStart = null;

            try
            {
                Antlr.Runtime.AstParserRuleReturnScope <GrammarAST, IToken> r = p.rule();
                RuleAST tree = (RuleAST)r.Tree;
                ruleStart = r.Start;
                GrammarTransformPipeline.SetGrammarPtr(g, tree);
                GrammarTransformPipeline.AugmentTokensWithOriginalPosition(g, tree);
                return(tree);
            }
            catch (Exception e)
            {
                tool.errMgr.ToolError(ErrorType.INTERNAL_ERROR,
                                      e,
                                      ruleStart,
                                      "error parsing rule created during left-recursion detection: " + ruleText);
            }
            return(null);
        }
Пример #2
0
        /** Given the raw AST of a grammar, create a grammar object
            associated with the AST. Once we have the grammar object, ensure
            that all nodes in tree referred to this grammar. Later, we will
            use it for error handling and generally knowing from where a rule
            comes from.
         */
        public virtual Grammar CreateGrammar(GrammarRootAST ast)
        {
            Grammar g;
            if (ast.grammarType == ANTLRParser.LEXER)
                g = new LexerGrammar(this, ast);
            else
                g = new Grammar(this, ast);

            // ensure each node has pointer to surrounding grammar
            GrammarTransformPipeline.SetGrammarPtr(g, ast);
            return g;
        }
Пример #3
0
        /** To process a grammar, we load all of its imported grammars into
         *  subordinate grammar objects. Then we merge the imported rules
         *  into the root grammar. If a root grammar is a combined grammar,
         *  we have to extract the implicit lexer. Once all this is done, we
         *  process the lexer first, if present, and then the parser grammar
         */
        public virtual void Process(Grammar g, bool gencode)
        {
            g.LoadImportedGrammars();

            GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this);

            transform.Process();

            LexerGrammar   lexerg;
            GrammarRootAST lexerAST;

            if (g.ast != null && g.ast.grammarType == ANTLRParser.COMBINED &&
                !g.ast.hasErrors)
            {
                lexerAST = transform.ExtractImplicitLexer(g); // alters g.ast
                if (lexerAST != null)
                {
                    if (grammarOptions != null)
                    {
                        lexerAST.cmdLineOptions = grammarOptions;
                    }

                    lexerg                    = new LexerGrammar(this, lexerAST);
                    lexerg.fileName           = g.fileName;
                    lexerg.originalGrammar    = g;
                    g.implicitLexer           = lexerg;
                    lexerg.implicitLexerOwner = g;

                    int prevErrors = errMgr.GetNumErrors();
                    ProcessNonCombinedGrammar(lexerg, gencode);
                    if (errMgr.GetNumErrors() > prevErrors)
                    {
                        return;
                    }

                    //				System.out.println("lexer tokens="+lexerg.tokenNameToTypeMap);
                    //				System.out.println("lexer strings="+lexerg.stringLiteralToTypeMap);
                }
            }
            if (g.implicitLexer != null)
            {
                g.ImportVocab(g.implicitLexer);
            }
            //		System.out.println("tokens="+g.tokenNameToTypeMap);
            //		System.out.println("strings="+g.stringLiteralToTypeMap);
            ProcessNonCombinedGrammar(g, gencode);
        }
        /** Return true if successful */
        public virtual bool TranslateLeftRecursiveRule(GrammarRootAST ast,
                                                       LeftRecursiveRule r,
                                                       string language)
        {
            //tool.log("grammar", ruleAST.toStringTree());
            GrammarAST prevRuleAST = r.ast;
            string     ruleName    = prevRuleAST.GetChild(0).Text;
            LeftRecursiveRuleAnalyzer leftRecursiveRuleWalker =
                new LeftRecursiveRuleAnalyzer(prevRuleAST, tool, ruleName, language);
            bool isLeftRec;

            try
            {
                //System.Console.WriteLine("TESTING ---------------\n" +
                //                   leftRecursiveRuleWalker.Text(ruleAST));
                isLeftRec = leftRecursiveRuleWalker.rec_rule();
            }
            catch (RecognitionException)
            {
                isLeftRec = false; // didn't match; oh well
            }
            if (!isLeftRec)
            {
                return(false);
            }

            // replace old rule's AST; first create text of altered rule
            GrammarAST RULES       = (GrammarAST)ast.GetFirstChildWithType(ANTLRParser.RULES);
            string     newRuleText = leftRecursiveRuleWalker.GetArtificialOpPrecRule();
            //System.Console.WriteLine("created: " + newRuleText);
            // now parse within the context of the grammar that originally created
            // the AST we are transforming. This could be an imported grammar so
            // we cannot just reference this.g because the role might come from
            // the imported grammar and not the root grammar (this.g)
            RuleAST t = ParseArtificialRule(prevRuleAST.g, newRuleText);

            // reuse the name token from the original AST since it refers to the proper source location in the original grammar
            ((GrammarAST)t.GetChild(0)).Token = ((GrammarAST)prevRuleAST.GetChild(0)).Token;

            // update grammar AST and set rule's AST.
            RULES.SetChild(prevRuleAST.ChildIndex, t);
            r.ast = t;

            // Reduce sets in newly created rule tree
            GrammarTransformPipeline transform = new GrammarTransformPipeline(g, g.tool);

            transform.ReduceBlocksToSets(r.ast);
            transform.ExpandParameterizedLoops(r.ast);

            // Rerun semantic checks on the new rule
            RuleCollector ruleCollector = new RuleCollector(g);

            ruleCollector.Visit(t, "rule");
            BasicSemanticChecks basics = new BasicSemanticChecks(g, ruleCollector);

            // disable the assoc element option checks because they are already
            // handled for the pre-transformed rule.
            basics.checkAssocElementOption = false;
            basics.Visit(t, "rule");

            // track recursive alt info for codegen
            r.recPrimaryAlts = new List <LeftRecursiveRuleAltInfo>();
            foreach (var altInfo in leftRecursiveRuleWalker.prefixAndOtherAlts)
            {
                r.recPrimaryAlts.Add(altInfo);
            }
            if (r.recPrimaryAlts.Count == 0)
            {
                tool.errMgr.GrammarError(ErrorType.NO_NON_LR_ALTS, g.fileName, ((GrammarAST)r.ast.GetChild(0)).Token, r.name);
            }

            r.recOpAlts = new OrderedHashMap <int, LeftRecursiveRuleAltInfo>();
            foreach (var pair in leftRecursiveRuleWalker.binaryAlts)
            {
                r.recOpAlts[pair.Key] = pair.Value;
            }
            foreach (var pair in leftRecursiveRuleWalker.ternaryAlts)
            {
                r.recOpAlts[pair.Key] = pair.Value;
            }
            foreach (var pair in leftRecursiveRuleWalker.suffixAlts)
            {
                r.recOpAlts[pair.Key] = pair.Value;
            }

            // walk alt info records and set their altAST to point to appropriate ALT subtree
            // from freshly created AST
            SetAltASTPointers(r, t);

            // update Rule to just one alt and add prec alt
            ActionAST arg = (ActionAST)r.ast.GetFirstChildWithType(ANTLRParser.ARG_ACTION);

            if (arg != null)
            {
                r.args       = ScopeParser.ParseTypedArgList(arg, arg.Text, g);
                r.args.type  = AttributeDict.DictType.ARG;
                r.args.ast   = arg;
                arg.resolver = r.alt[1]; // todo: isn't this Rule or something?
            }

            // define labels on recursive rule refs we delete; they don't point to nodes of course
            // these are so $label in action translation works
            foreach (System.Tuple <GrammarAST, string> pair in leftRecursiveRuleWalker.leftRecursiveRuleRefLabels)
            {
                GrammarAST       labelNode   = pair.Item1;
                GrammarAST       labelOpNode = (GrammarAST)labelNode.Parent;
                GrammarAST       elementNode = (GrammarAST)labelOpNode.GetChild(1);
                LabelElementPair lp          = new LabelElementPair(g, labelNode, elementNode, labelOpNode.Type);
                r.alt[1].labelDefs.Map(labelNode.Text, lp);
            }
            // copy to rule from walker
            r.leftRecursiveRuleRefLabels = leftRecursiveRuleWalker.leftRecursiveRuleRefLabels;

            tool.Log("grammar", "added: " + t.ToStringTree());
            return(true);
        }