Ejemplo n.º 1
0
        public void Try(string ffn, string input, ref Dictionary <string, string> results)
        {
            var now       = DateTime.Now.ToString();
            var errors    = new StringBuilder();
            var str       = new AntlrInputStream(input);
            var lexer     = new ANTLRv2Lexer(str);
            var tokens    = new CommonTokenStream(lexer);
            var parser    = new ANTLRv2Parser(tokens);
            var elistener = new ErrorListener <IToken>(parser, lexer, 0);

            parser.AddErrorListener(elistener);
            var tree            = parser.grammar_();
            var error_file_name = ffn;

            error_file_name = error_file_name.EndsWith(".g2")
                ? (error_file_name.Substring(0, error_file_name.Length - 3) + ".txt") : error_file_name;
            error_file_name = error_file_name.EndsWith(".g")
                ? (error_file_name.Substring(0, error_file_name.Length - 2) + ".txt") : error_file_name;

            var new_ffn = ffn;

            new_ffn = new_ffn.EndsWith(".g2")
                ? (new_ffn.Substring(0, new_ffn.Length - 3) + ".g4") : new_ffn;
            new_ffn = new_ffn.EndsWith(".g")
                ? (new_ffn.Substring(0, new_ffn.Length - 2) + ".g4") : new_ffn;

            if (elistener.had_error)
            {
                results.Add(error_file_name, errors.ToString());
                return;
            }
            else
            {
                errors.AppendLine("File " + ffn + " parsed successfully.");
                errors.AppendLine("Date: " + now);
            }

            // Transforms derived from two sources:
            // https://github.com/senseidb/sensei/pull/23
            var(text_before, other) = TreeEdits.TextToLeftOfLeaves(tokens, tree);

            // Remove "header".
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                var nodes = engine.parseExpression(
                    @"//header_",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                            .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                foreach (var n in nodes)
                {
                    TreeEdits.Delete(n);
                }
            }

            // Remove classDef action blocks for now.
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                var nodes = engine.parseExpression(
                    @"//classDef/actionBlock",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                            .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                foreach (var n in nodes)
                {
                    TreeEdits.Delete(n);
                }
            }

            // Let's take care of options first. That's because we can't
            // determine if this is a combined grammar or not.
            // Remove unused options at top of grammar def.
            // This specifically looks at the options at the top of the file,
            // not rule-based options. That will be handled separately below.
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                var options = engine.parseExpression(
                    @"//(fileOptionsSpec | parserOptionsSpec | lexerOptionsSpec | treeOptionsSpec)",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                              .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree).ToList();
                var nodes = engine.parseExpression(
                    @"//(fileOptionsSpec | parserOptionsSpec | lexerOptionsSpec | treeParserOptionsSpec)
                            /(option | lexerOption)
                                [id/*
                                        [
                                        text() = 'output'
                                        or text() = 'backtrack'
                                        or text() = 'buildAST'
                                        or text() = 'classHeaderSuffix'
                                        or text() = 'memoize'
                                        or text() = 'ASTLabelType'
                                        or text() = 'rewrite'
                                        or text() = 'k'
                                        or text() = 'exportVocab'
                                        or text() = 'testLiterals'
                                        or text() = 'interactive'
                                        or text() = 'charVocabulary'
                                        or text() = 'defaultErrorHandler'
                                        ]]",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                            .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                TreeEdits.Delete(nodes);
                foreach (var opt in options)
                {
                    if (opt.ChildCount == 3)
                    {
                        TreeEdits.Delete(opt);
                    }
                }
            }

            // Delete rule options.
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                var nodes = engine.parseExpression(
                    @"//rule_/ruleOptionsSpec
                            /option
                                [id
                                    /(TOKEN_REF | RULE_REF)
                                        [text() = 'output'
                                        or text() = 'backtrack'
                                        or text() = 'memoize'
                                        or text() = 'ASTLabelType'
                                        or text() = 'rewrite'
                                        or text() = 'k'
                                        or text() = 'exportVocab'
                                        or text() = 'testLiterals'
                                        or text() = 'interactive'
                                        or text() = 'charVocabulary'
                                        or text() = 'defaultErrorHandler'
                                        ]]",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                            .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                TreeEdits.Delete(nodes);
                var options = engine.parseExpression(
                    @"//rule_/ruleOptionsSpec",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                              .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                foreach (var os in options)
                {
                    if (os.ChildCount == 3)
                    {
                        TreeEdits.Delete(os);
                    }
                }
            }

            // Parser and Lexer in One Definition
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                var parser_nodes = engine.parseExpression(
                    @"//parserSpec",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                                   .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                var lexer_nodes = engine.parseExpression(
                    @"//lexerSpec",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                                  .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                var tree_nodes = engine.parseExpression(
                    @"//treeParserSpec",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                                 .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                // Can this be a "combined" grammar? That can happen only if
                // one parser and one lexer decl and no tree decl. Options for
                // the lexer must be removed too.
                if (parser_nodes.Count() == 1 && lexer_nodes.Count() == 1 && tree_nodes.Count() == 0)
                {
                    var lexerSpec = lexer_nodes.First() as ANTLRv2Parser.LexerSpecContext;
                    if (lexerSpec.lexerOptionsSpec() == null)
                    {
                        // Nuke lexer class decl because it's a combined grammar.
                        TreeEdits.Delete(lexerSpec);
                        lexerSpec = null;
                    }
                    // Rewrite the parser spec.
                    var parserSpec = parser_nodes.First() as ANTLRv2Parser.ParserSpecContext;
                    var c          = parserSpec.CLASS();
                    var i          = parserSpec.id();
                    var e          = parserSpec.EXTENDS();
                    var p          = parserSpec.PARSER();
                    var s          = parserSpec.superClass();
                    var new_sym    = new TerminalNodeImpl(new CommonToken(ANTLRv4Lexer.GRAMMAR)
                    {
                        Line = -1, Column = -1, Text = "grammar"
                    });
                    text_before.TryGetValue(c as TerminalNodeImpl, out string v);
                    if (v != null)
                    {
                        text_before.Add(new_sym, v);
                    }
                    TreeEdits.Replace(c, (in IParseTree n, out bool cc) =>
                    {
                        cc = false;
                        return(new_sym);
                    });
Ejemplo n.º 2
0
        public void Try(string ffn, string input, ref Dictionary <string, string> results)
        {
            var now       = DateTime.Now.ToString();
            var errors    = new StringBuilder();
            var str       = new AntlrInputStream(input);
            var lexer     = new ANTLRv3Lexer(str);
            var tokens    = new CommonTokenStream(lexer);
            var parser    = new ANTLRv3Parser(tokens);
            var elistener = new ErrorListener <IToken>(parser, lexer, 0);

            parser.AddErrorListener(elistener);
            var tree            = parser.grammarDef();
            var error_file_name = ffn;

            error_file_name = error_file_name.EndsWith(".g3")
                ? (error_file_name.Substring(0, error_file_name.Length - 3) + ".txt") : error_file_name;
            error_file_name = error_file_name.EndsWith(".g")
                ? (error_file_name.Substring(0, error_file_name.Length - 2) + ".txt") : error_file_name;

            var new_ffn = ffn;

            new_ffn = new_ffn.EndsWith(".g3")
                ? (new_ffn.Substring(0, new_ffn.Length - 3) + ".g4") : new_ffn;
            new_ffn = new_ffn.EndsWith(".g")
                ? (new_ffn.Substring(0, new_ffn.Length - 2) + ".g4") : new_ffn;

            if (elistener.had_error)
            {
                results.Add(error_file_name, errors.ToString());
                return;
            }
            else
            {
                errors.AppendLine("File " + ffn + " parsed successfully.");
                errors.AppendLine("Date: " + now);
            }

            // Transforms derived from two sources:
            // https://github.com/senseidb/sensei/pull/23
            var(text_before, other) = TreeEdits.TextToLeftOfLeaves(tokens, tree);

            // Remove unused options at top of grammar def.
            // This specifically looks at the options at the top of the file,
            // not rule-based options. That will be handled separately below.
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                // Allow language, tokenVocab, TokenLabelType, superClass
                var nodes = engine.parseExpression(
                    @"//grammarDef/optionsSpec
                            /option
                                [id
                                    /(TOKEN_REF | RULE_REF)
                                        [text() = 'output'
                                        or text() = 'backtrack'
                                        or text() = 'memoize'
                                        or text() = 'ASTLabelType'
                                        or text() = 'rewrite'
                                        ]]",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                            .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                TreeEdits.Delete(nodes);
                var options = engine.parseExpression(
                    @"//grammarDef/optionsSpec",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                              .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                foreach (var os in options)
                {
                    if (os.ChildCount == 3)
                    {
                        TreeEdits.Delete(os);
                    }
                }
            }

            // Fix options in the beginning of rules.
            // See https://theantlrguy.atlassian.net/wiki/spaces/ANTLR3/pages/2687029/Rule+and+subrule+options
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                // Allow language, tokenVocab, TokenLabelType, superClass
                var nodes = engine.parseExpression(
                    @"//rule_/optionsSpec
                            /option
                                [id
                                    /(TOKEN_REF | RULE_REF)
                                        [text() = 'output'
                                        or text() = 'backtrack'
                                        or text() = 'memoize'
                                        or text() = 'ASTLabelType'
                                        or text() = 'rewrite'
                                        ]]",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                            .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                TreeEdits.Delete(nodes);
                var options = engine.parseExpression(
                    @"//rule_/optionsSpec",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                              .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                foreach (var os in options)
                {
                    if (os.ChildCount == 3)
                    {
                        TreeEdits.Delete(os);
                    }
                }
            }

            // Use new tokens{} syntax
            using (AntlrTreeEditing.AntlrDOM.AntlrDynamicContext dynamicContext =
                       new AntlrTreeEditing.AntlrDOM.ConvertToDOM().Try(tree, parser))
            {
                org.eclipse.wst.xml.xpath2.processor.Engine engine =
                    new org.eclipse.wst.xml.xpath2.processor.Engine();
                var nodes = engine.parseExpression(
                    @"//tokensSpec
                            /tokenSpec
                                /SEMI",
                    new StaticContextBuilder()).evaluate(
                    dynamicContext, new object[] { dynamicContext.Document })
                            .Select(x => (x.NativeValue as AntlrTreeEditing.AntlrDOM.AntlrElement).AntlrIParseTree);
                if (nodes.Any())
                {
                    // Delete tha last ";" in tokens list--change in syntax.
                    var last = nodes.Last();
                    TreeEdits.Delete(last);
                    // Replace all remaining ";" with ",".
                    TreeEdits.Replace(tree, (in IParseTree n, out bool c) =>
                    {
                        c = true;
                        if (!nodes.Contains(n) && n != last)
                        {
                            return(null);
                        }
                        var t       = n as TerminalNodeImpl;
                        var new_sym = new TerminalNodeImpl(new CommonToken(ANTLRv4Lexer.COMMA)
                        {
                            Line = -1, Column = -1, Text = ","
                        });
                        text_before.TryGetValue(t, out string v);
                        if (v != null)
                        {
                            text_before.Add(new_sym, v);
                        }
                        return(new_sym);
                    });