简体   繁体   English

Java 语法的访问者方法在 ANTLR 4.4 中不起作用

[英]Visitor methods for Java grammar not working in ANTLR 4.4

I am new to ANTLR framework.我是 ANTLR 框架的新手。 I have been working around this for a week.我一直在解决这个问题一个星期。 Now am in a situation where i need to parse the Java file and extract the data.现在我需要解析 Java 文件并提取数据。 Am using ANTLR 4 for parsing.正在使用 ANTLR 4 进行解析。 I create the Lexer, Parser and Visitor files using ANTLR in built tool.我在内置工具中使用 ANTLR 创建 Lexer、Parser 和 Visitor 文件。 When I try to over ride the Visitor method I doesn't gets called and returns null value.当我尝试覆盖访问者方法时,我不会被调用并返回null值。

Here is the coding.这是编码。

I have generated JavaLexer, JavaParser, JavaVisitor, JavaBaseVisitor, JavaListener我已经生成了JavaLexer, JavaParser, JavaVisitor, JavaBaseVisitor, JavaListener

package com.antlr;

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

import java.io.FileInputStream;
import java.io.InputStream;


public class ExtractInterfaceVisitor {


    public  static class AnnVisitor extends JavaBaseVisitor<String> {

        @Override
        public String visitAnnotation (JavaParser.AnnotationContext ctx) 
        {
            System.out.println("Annotation");
            return ctx.getText();
         }

@Override
 public String visitClassDeclaration( JavaParser.ClassDeclarationContext ctx)
 {

     System.out.println("Class Declaration");
     return ctx.getText(); 
 }
 }


public static void main(String[] args) throws Exception {
   String inputFile = null;
   inputFile =  "C:/Users/User/Desktop/antlr/java1/Demo.java"; //Contains a Java File
   InputStream is = System.in;
   is = new FileInputStream(inputFile);

   ANTLRInputStream input = new ANTLRInputStream(is);
   JavaLexer lexer = new JavaLexer(input);
   CommonTokenStream tokens = new CommonTokenStream(lexer);
   JavaParser parser = new JavaParser(tokens);
   parser.setBuildParseTree(true);      // tell ANTLR to build a parse tree
   ParseTree tree = parser.compilationUnit(); // parse
   // show tree in text form
   //System.out.println(tree.toStringTree(parser));

   AnnVisitor Visitor = new AnnVisitor();
   String result = Visitor.visit(tree);
   System.out.println("visitor result = "+result);
    }
}

Demo.java演示.java

@ClassAnnotation(Value="Class")
public class Demo {

    @MethodAnnotation(Value="Method")
    void MethodName(int x, String y) {  }
    int x;

    int[ ] g(/*no args*/)
    {   }

    int average()
    {   }

    List<Map<String, Integer>>[] h() { return null; }
}

Java.g4 Java.g4

/** Java 1.6 grammar (ANTLR v4). Derived from

    http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf

    and JavaParser.g from ANTLR v3
 */
grammar Java;

@lexer::members {
  protected boolean enumIsKeyword = true;
  protected boolean assertIsKeyword = true;
}

// starting point for parsing a java file
compilationUnit
    :   packageDeclaration? importDeclaration* typeDeclaration*
        EOF
    ;

packageDeclaration
    :   'package' qualifiedName ';'
    ;

importDeclaration
    :   'import' 'static'? qualifiedName ('.' '*')? ';'
    ;

typeDeclaration
    :   classOrInterfaceModifier*
        (   classDeclaration
        |   interfaceDeclaration
        |   enumDeclaration
        )
    |   ';'
    ;

classDeclaration
    :   'class' Identifier typeParameters? ('extends' type)?
        ('implements' typeList)?
        classBody
    ;

enumDeclaration
    :   ENUM Identifier ('implements' typeList)? enumBody
    ;

interfaceDeclaration
    :   normalInterfaceDeclaration
    |   annotationTypeDeclaration
    ;

classOrInterfaceModifier
    :   annotation   // class or interface
    |   'public'     // class or interface
    |   'protected'  // class or interface
    |   'private'    // class or interface
    |   'abstract'   // class or interface
    |   'static'     // class or interface
    |   'final'      // class only -- does not apply to interfaces
    |   'strictfp'   // class or interface
    ;

modifiers
    :   modifier*
    ;

typeParameters
    :   '<' typeParameter (',' typeParameter)* '>'
    ;

typeParameter
    :   Identifier ('extends' typeBound)?
    ;

typeBound
    :   type ('&' type)*
    ;

enumBody
    :   '{' enumConstants? ','? enumBodyDeclarations? '}'
    ;

enumConstants
    :   enumConstant (',' enumConstant)*
    ;

enumConstant
    :   annotations? Identifier arguments? classBody?
    ;

enumBodyDeclarations
    :   ';' (classBodyDeclaration)*
    ;

normalInterfaceDeclaration
    :   'interface' Identifier typeParameters? ('extends' typeList)? interfaceBody
    ;

typeList
    :   type (',' type)*
    ;

classBody
    :   '{' classBodyDeclaration* '}'
    ;

interfaceBody
    :   '{' interfaceBodyDeclaration* '}'
    ;

classBodyDeclaration
    :   ';'
    |   'static'? block
    |   modifiers member
    ;

member
    :   genericMethodDeclaration
    |   methodDeclaration
    |   fieldDeclaration
    |   constructorDeclaration
    |   interfaceDeclaration
    |   classDeclaration
    ;

methodDeclaration
    :   type Identifier formalParameters ('[' ']')* methodDeclarationRest
    |   'void' Identifier formalParameters methodDeclarationRest
    ;

methodDeclarationRest
    :   ('throws' qualifiedNameList)?
        (   methodBody
        |   ';'
        )
    ;

genericMethodDeclaration
    :   typeParameters methodDeclaration
    ;

fieldDeclaration
    :   type variableDeclarators ';'
    ;

constructorDeclaration
    :   typeParameters? Identifier formalParameters
        ('throws' qualifiedNameList)? constructorBody
    ;

interfaceBodyDeclaration
    :   modifiers interfaceMemberDecl
    |   ';'
    ;

interfaceMemberDecl
    :   interfaceMethodOrFieldDecl
    |   interfaceGenericMethodDecl
    |   'void' Identifier voidInterfaceMethodDeclaratorRest
    |   interfaceDeclaration
    |   classDeclaration
    ;

interfaceMethodOrFieldDecl
    :   type Identifier interfaceMethodOrFieldRest
    ;

interfaceMethodOrFieldRest
    :   constantDeclaratorsRest ';'
    |   interfaceMethodDeclaratorRest
    ;

voidMethodDeclaratorRest
    :   formalParameters ('throws' qualifiedNameList)?
        (   methodBody
        |   ';'
        )
    ;

interfaceMethodDeclaratorRest
    :   formalParameters ('[' ']')* ('throws' qualifiedNameList)? ';'
    ;

interfaceGenericMethodDecl
    :   typeParameters (type | 'void') Identifier
        interfaceMethodDeclaratorRest
    ;

voidInterfaceMethodDeclaratorRest
    :   formalParameters ('throws' qualifiedNameList)? ';'
    ;

constantDeclarator
    :   Identifier constantDeclaratorRest
    ;

variableDeclarators
    :   variableDeclarator (',' variableDeclarator)*
    ;

variableDeclarator
    :   variableDeclaratorId ('=' variableInitializer)?
    ;

constantDeclaratorsRest
    :   constantDeclaratorRest (',' constantDeclarator)*
    ;

constantDeclaratorRest
    :   ('[' ']')* '=' variableInitializer
    ;

variableDeclaratorId
    :   Identifier ('[' ']')*
    ;

variableInitializer
    :   arrayInitializer
    |   expression
    ;

arrayInitializer
    :   '{' (variableInitializer (',' variableInitializer)* (',')? )? '}'
    ;

modifier
    :   annotation
    |   'public'
    |   'protected'
    |   'private'
    |   'static'
    |   'abstract'
    |   'final'
    |   'native'
    |   'synchronized'
    |   'transient'
    |   'volatile'
    |   'strictfp'
    ;

packageOrTypeName
    :   qualifiedName
    ;

enumConstantName
    :   Identifier
    ;

typeName
    :   qualifiedName
    ;

type:   classOrInterfaceType ('[' ']')*
    |   primitiveType ('[' ']')*
    ;

classOrInterfaceType
    :   Identifier typeArguments? ('.' Identifier typeArguments? )*
    ;

primitiveType
    :   'boolean'
    |   'char'
    |   'byte'
    |   'short'
    |   'int'
    |   'long'
    |   'float'
    |   'double'
    ;

variableModifier
    :   'final'
    |   annotation
    ;

typeArguments
    :   '<' typeArgument (',' typeArgument)* '>'
    ;

typeArgument
    :   type
    |   '?' (('extends' | 'super') type)?
    ;

qualifiedNameList
    :   qualifiedName (',' qualifiedName)*
    ;

formalParameters
    :   '(' formalParameterDecls? ')'
    ;

formalParameterDecls
    :   variableModifiers type formalParameterDeclsRest
    ;

formalParameterDeclsRest
    :   variableDeclaratorId (',' formalParameterDecls)?
    |   '...' variableDeclaratorId
    ;

methodBody
    :   block
    ;

constructorBody
    :   '{' explicitConstructorInvocation? blockStatement* '}'
    ;

explicitConstructorInvocation
    :   nonWildcardTypeArguments? ('this' | 'super') arguments ';'
    |   primary '.' nonWildcardTypeArguments? 'super' arguments ';'
    ;

qualifiedName
    :   Identifier ('.' Identifier)*
    ;

literal
    :   integerLiteral
    |   FloatingPointLiteral
    |   CharacterLiteral
    |   StringLiteral
    |   booleanLiteral
    |   'null'
    ;

integerLiteral
    :   HexLiteral
    |   OctalLiteral
    |   DecimalLiteral
    ;

booleanLiteral
    :   'true'
    |   'false'
    ;

// ANNOTATIONS

annotations
    :   annotation+
    ;

annotation
    :   '@' annotationName ( '(' ( elementValuePairs | elementValue )? ')' )?
    ;

annotationName
    : Identifier ('.' Identifier)*
    ;

elementValuePairs
    :   elementValuePair (',' elementValuePair)*
    ;

elementValuePair
    :   Identifier '=' elementValue
    ;

elementValue
    :   expression
    |   annotation
    |   elementValueArrayInitializer
    ;

elementValueArrayInitializer
    :   '{' (elementValue (',' elementValue)*)? (',')? '}'
    ;

annotationTypeDeclaration
    :   '@' 'interface' Identifier annotationTypeBody
    ;

annotationTypeBody
    :   '{' (annotationTypeElementDeclaration)* '}'
    ;

annotationTypeElementDeclaration
    :   modifiers annotationTypeElementRest
    ;

annotationTypeElementRest
    :   type annotationMethodOrConstantRest ';'
    |   classDeclaration ';'?
    |   normalInterfaceDeclaration ';'?
    |   enumDeclaration ';'?
    |   annotationTypeDeclaration ';'?
    ;

annotationMethodOrConstantRest
    :   annotationMethodRest
    |   annotationConstantRest
    ;

annotationMethodRest
    :   Identifier '(' ')' defaultValue?
    ;

annotationConstantRest
    :   variableDeclarators
    ;

defaultValue
    :   'default' elementValue
    ;

// STATEMENTS / BLOCKS

block
    :   '{' blockStatement* '}'
    ;

blockStatement
    :   localVariableDeclarationStatement
    |   classDeclaration
    |   interfaceDeclaration
    |   statement
    ;

localVariableDeclarationStatement
    :    localVariableDeclaration ';'
    ;

localVariableDeclaration
    :   variableModifiers type variableDeclarators
    ;

variableModifiers
    :   variableModifier*
    ;

statement
    : block
    |   ASSERT expression (':' expression)? ';'
    |   'if' parExpression statement ('else' statement)?
    |   'for' '(' forControl ')' statement
    |   'while' parExpression statement
    |   'do' statement 'while' parExpression ';'
    |   'try' block
        ( catches 'finally' block
        | catches
        | 'finally' block
        )
    |   'switch' parExpression switchBlock
    |   'synchronized' parExpression block
    |   'return' expression? ';'
    |   'throw' expression ';'
    |   'break' Identifier? ';'
    |   'continue' Identifier? ';'
    |   ';'
    |   statementExpression ';'
    |   Identifier ':' statement
    ;

catches
    :   catchClause (catchClause)*
    ;

catchClause
    :   'catch' '(' formalParameter ')' block
    ;

formalParameter
    :   variableModifiers type variableDeclaratorId
    ;

switchBlock
    :   '{' switchBlockStatementGroup* switchLabel* '}'
    ;

switchBlockStatementGroup
    :   switchLabel+ blockStatement*
    ;

switchLabel
    :   'case' constantExpression ':'
    |   'case' enumConstantName ':'
    |   'default' ':'
    ;

forControl
    :   enhancedForControl
    |   forInit? ';' expression? ';' forUpdate?
    ;

forInit
    :   localVariableDeclaration
    |   expressionList
    ;

enhancedForControl
    :   variableModifiers type Identifier ':' expression
    ;

forUpdate
    :   expressionList
    ;

// EXPRESSIONS

parExpression
    :   '(' expression ')'
    ;

expressionList
    :   expression (',' expression)*
    ;

statementExpression
    :   expression
    ;

constantExpression
    :   expression
    ;

expression
    :   primary
    |   expression '.' Identifier
    |   expression '.' 'this'
    |   expression '.' 'super' '(' expressionList? ')'
    |   expression '.' 'new' Identifier '(' expressionList? ')'
    |   expression '.' 'super' '.' Identifier arguments?
    |   expression '.' explicitGenericInvocation
    |   expression '[' expression ']'
    |   expression '(' expressionList? ')'
    |   expression ('++' | '--')
    |   ('+'|'-'|'++'|'--') expression
    |   ('~'|'!') expression
    |   '(' type ')' expression
    |   'new' creator
    |   expression ('*'|'/'|'%') expression
    |   expression ('+'|'-') expression
    |   expression ('<' '<' | '>' '>' '>' | '>' '>') expression
    |   expression ('<' '=' | '>' '=' | '>' | '<') expression
    |   expression 'instanceof' type
    |   expression ('==' | '!=') expression
    |   expression '&' expression
    |   expression '^' expression
    |   expression '|' expression
    |   expression '&&' expression
    |   expression '||' expression
    |   expression '?' expression ':' expression
    |   expression
        ('^='<assoc=right>
        |'+='<assoc=right>
        |'-='<assoc=right>
        |'*='<assoc=right>
        |'/='<assoc=right>
        |'&='<assoc=right>
        |'|='<assoc=right>
        |'='<assoc=right>
        |'>' '>' '='<assoc=right>
        |'>' '>' '>' '='<assoc=right>
        |'<' '<' '='<assoc=right>
        |'%='<assoc=right>
        )
        expression
    ;

primary
    :   '(' expression ')'
    |   'this'
    |   'super'
    |   literal
    |   Identifier
    |   type '.' 'class'
    |   'void' '.' 'class'
    ;

creator
    :   nonWildcardTypeArguments createdName classCreatorRest
    |   createdName (arrayCreatorRest | classCreatorRest)
    ;

createdName
    :   classOrInterfaceType
    |   primitiveType
    ;

innerCreator
    :   nonWildcardTypeArguments? Identifier classCreatorRest
    ;

explicitGenericInvocation
    :   nonWildcardTypeArguments Identifier arguments
    ;

arrayCreatorRest
    :   '['
        (   ']' ('[' ']')* arrayInitializer
        |   expression ']' ('[' expression ']')* ('[' ']')*
        )
    ;

classCreatorRest
    :   arguments classBody?
    ;

nonWildcardTypeArguments
    :   '<' typeList '>'
    ;

arguments
    :   '(' expressionList? ')'
    ;

// LEXER

HexLiteral : '0' ('x'|'X') HexDigit+ IntegerTypeSuffix? ;

DecimalLiteral : ('0' | '1'..'9' '0'..'9'*) IntegerTypeSuffix? ;

OctalLiteral : '0' ('0'..'7')+ IntegerTypeSuffix? ;

fragment
HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
IntegerTypeSuffix : ('l'|'L') ;

FloatingPointLiteral
    :   ('0'..'9')+ '.' ('0'..'9')* Exponent? FloatTypeSuffix?
    |   '.' ('0'..'9')+ Exponent? FloatTypeSuffix?
    |   ('0'..'9')+ Exponent FloatTypeSuffix?
    |   ('0'..'9')+ FloatTypeSuffix
    |   ('0x' | '0X') (HexDigit )*
        ('.' (HexDigit)*)?
        ( 'p' | 'P' )
        ( '+' | '-' )?
        ( '0' .. '9' )+
        FloatTypeSuffix?
    ;

fragment
Exponent : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
FloatTypeSuffix : ('f'|'F'|'d'|'D') ;

CharacterLiteral
    :   '\'' ( EscapeSequence | ~('\''|'\\') ) '\''
    ;

StringLiteral
    :  '"' ( EscapeSequence | ~('\\'|'"') )* '"'
    ;

fragment
EscapeSequence
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UnicodeEscape
    |   OctalEscape
    ;

fragment
OctalEscape
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UnicodeEscape
    :   '\\' 'u' HexDigit HexDigit HexDigit HexDigit
    ;

ENUM:   'enum' {if (!enumIsKeyword) setType(Identifier);}
    ;

ASSERT
    :   'assert' {if (!assertIsKeyword) setType(Identifier);}
    ;

Identifier
    :   Letter (Letter|JavaIDDigit)*
    ;

/**I found this char range in JavaCC's grammar, but Letter and Digit overlap.
   Still works, but...
 */
fragment
Letter
    :  '\u0024' |
       '\u0041'..'\u005a' |
       '\u005f' |
       '\u0061'..'\u007a' |
       '\u00c0'..'\u00d6' |
       '\u00d8'..'\u00f6' |
       '\u00f8'..'\u00ff' |
       '\u0100'..'\u1fff' |
       '\u3040'..'\u318f' |
       '\u3300'..'\u337f' |
       '\u3400'..'\u3d2d' |
       '\u4e00'..'\u9fff' |
       '\uf900'..'\ufaff'
    ;

fragment
JavaIDDigit
    :  '\u0030'..'\u0039' |
       '\u0660'..'\u0669' |
       '\u06f0'..'\u06f9' |
       '\u0966'..'\u096f' |
       '\u09e6'..'\u09ef' |
       '\u0a66'..'\u0a6f' |
       '\u0ae6'..'\u0aef' |
       '\u0b66'..'\u0b6f' |
       '\u0be7'..'\u0bef' |
       '\u0c66'..'\u0c6f' |
       '\u0ce6'..'\u0cef' |
       '\u0d66'..'\u0d6f' |
       '\u0e50'..'\u0e59' |
       '\u0ed0'..'\u0ed9' |
       '\u1040'..'\u1049'
   ;

COMMENT
    :   '/*' .*? '*/'    -> channel(HIDDEN) // match anything between /* and */
    ;
WS  :   [ \r\t\u000C\n]+ -> channel(HIDDEN)
    ;

LINE_COMMENT
    : '//' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN)
    ;

The Final out put which i get is: Visitor result = null我得到的最终输出是: Visitor result = null

I don't know where i went wrong.我不知道我哪里出错了。 It doesn't call the visit methods also.它也不调用访问方法。 Please correct me.请纠正我。

The generated parse tree visitor extends AbstractParseTreeVisitor , which has two methods which would be helpful to override to get the result you are looking for.生成的解析树访问者扩展了AbstractParseTreeVisitor ,它有两个方法可以帮助重写以获得您正在寻找的结果。

Firstly, AbstractParseTreeVisitor#defaultResult() returns the default result for every node in the parse tree you visit.首先, AbstractParseTreeVisitor#defaultResult()返回您访问的解析树中每个节点的默认结果。 By default, it returns null .默认情况下,它返回null

Second, AbstractParseTreeVisitor#aggregateResult(T,T) aggregates the last node's visited result with the total result so far.其次, AbstractParseTreeVisitor#aggregateResult(T,T)将最后一个节点的访问结果与到目前为止的总结果聚合。

You have not overridden either of these methods, so aggregateResult(T,T) is returning the default result of the last parse tree node visited, which is giving you a null result.您没有覆盖这些方法中的任何一个,因此 aggregateResult(T,T) 返回最后访问的解析树节点的默认结果,这给您一个null结果。

So, if you want to fix this, I would override defaultResult to look something like this:所以,如果你想解决这个问题,我会覆盖defaultResult看起来像这样:

@Override
public String aggregateResult(String aggregate, String nextResult) {
    if (aggregate == null) {
        return nextResult;
    }

    if (nextResult == null) {
        return aggregrate;
    }

    StringBuilder sb = new StringBuilder(aggregate);
    sb.append(" ");
    sb.append(nextResult);

    return sb.toString();
}

If you don't want to do the null checks in your aggregateResult override, you could override defaultResult to return the empty String and then have aggregateResult append every result to the aggregate, but I personally prefer the first solution.如果你不想做null检查你的aggregateResult覆盖,您可以覆盖defaultResult返回空字符串,然后有aggregateResult每个结果追加到聚集,但我个人更喜欢第一个解决方案。

I also used ANTLR before but I ended up using Eclipse JDT is updated for JAVA8 and its really simple to get started with the AST.我之前也使用过 ANTLR,但我最终使用了 Eclipse JDT 针对 JAVA8 进行了更新,并且开始使用 AST 非常简单。

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;

/**
 *
 * @author Lethe
 */
public class Parser {

    public Parser() {
    }

    public String readFile(String path, Charset encoding)
            throws IOException {
        byte[] encoded = Files.readAllBytes(Paths.get(path));
        return new String(encoded, encoding);
    }

    public void parseSource() {

        try {
            ASTParser parser = ASTParser.newParser(AST.JLS3);
            String source = readFile("test.java", Charset.defaultCharset());
            //parser.setSource("public class A { int i = 9;  \n int j; \n ArrayList<Integer> al = new ArrayList<Integer>();j=1000; }".toCharArray());
            parser.setSource(source.toCharArray());
            parser.setKind(ASTParser.K_COMPILATION_UNIT);
            //ASTNode node = parser.createAST(null);

            final CompilationUnit cu = (CompilationUnit) parser.createAST(null);

            cu.accept(new ASTVisitor() {

                Set names = new HashSet();

                public boolean visit(VariableDeclarationFragment node) {
                    SimpleName name = node.getName();
                    this.names.add(name.getIdentifier());
                    System.out.println("Declaration of '" + name + "' at line" + cu.getLineNumber(name.getStartPosition()));
                    return false; // do not continue to avoid usage info
                }

                public boolean visit(SimpleName node) {
                    if (this.names.contains(node.getIdentifier())) {
                        System.out.println("Usage of '" + node + "' at line " + cu.getLineNumber(node.getStartPosition()));
                    }
                    return true;
                }

                public boolean visit(SingleMemberAnnotation annotation) {
                    System.out.println(annotation.getTypeName());
                    System.out.println(annotation.getValue());
                    return true;
                }

                public boolean visit(NormalAnnotation annotation) {
                    System.out.println(annotation.getTypeName());
                    return true;
                }

                public boolean visit(MarkerAnnotation annotation) {
                    System.out.println(annotation.getTypeName());
                    return true;
                }

            });
        } catch (IOException ex) {
            Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

Hope this helps with your AST http://www.eclipse.org/jdt/apt/index.php ^_^希望这有助于您的 AST http://www.eclipse.org/jdt/apt/index.php ^_^

First some advice:先给个建议:

  1. You should check out the definitive antlr reference .您应该查看最终的 antlr 参考 One week is enough of time for that.一周时间足够了。 In there, it says and I quote在那里,它说,我引用

" Visitors walk parse trees by explicitly calling interface ParseTreeVisitor's visit() method on child nodes. " 访问者通过在子节点上显式调用接口 ParseTreeVisitor 的访问()方法来遍历解析树。

  1. The class "ExtractInterfaceVisitor" is quite redundant, since You only have one inner class inside of it... “ExtractInterfaceVisitor”类是非常多余的,因为它里面只有一个内部类......

  2. Try debugging the code, put breakpoints in your visit methods and see what happens.尝试调试代码,在访问方法中放置断点,看看会发生什么。 Chances are that only top-level-rule visitor will be executed.有可能只执行顶级规则访问者。

If You don't see the output "Class Declaration", I could only assume that Demo.java does not start with a class declaration.如果您没有看到输出“类声明”,我只能假设 Demo.java 没有以类声明开头。

EDIT: The first visit method that is called is the one corresponding to the parser rule that matches the first line in Demo.java.编辑:调用的第一个访问方法是对应于与 Demo.java 中第一行匹配的解析器规则的方法。

I was facing the exact same issue on Eclipse Neon and I resolved it in the following way.我在 Eclipse Neon 上遇到了完全相同的问题,我通过以下方式解决了它。

Step1: I removed Antlr4 sdk from eclipse.第 1 步:我从 eclipse 中删除了 Antlr4 sdk。 This is a plugin to auto generate Visitor and Listener classes after parsing Java.g4 grammar file.这是一个在解析 Java.g4 语法文件后自动生成 Visitor 和 Listener 类的插件。

Step2: Created a source folder in my project Step2:在我的项目中创建一个源文件夹

src/main/antlr4

Inside this I created the package在这个里面我创建了包

com.helper.tony.grammar

I placed my Java.g4 file inside this package.我把我的 Java.g4 文件放在这个包里。 This was done to create my Visitors and Listeners with the same package structure in the output directory.这样做是为了在输出目录中创建具有相同包结构的访问者和侦听器。 Output directory location is输出目录位置是

target/generated-sources/antlr4

as indicated by output directory tag in pom.xml.如 pom.xml 中的输出目录标记所示。 I also added this into my build path.我还将它添加到我的构建路径中。

Step3: Setting pom file properly.I added tag into my pom file and did set maven compiler plugin source and target version to Java 1.8.第三步:正确设置 pom 文件。我在 pom 文件中添加了标签,并将 maven 编译器插件源和目标版本设置为 Java 1.8。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.helper.mani</groupId>
<artifactId>builder_factory</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
    <!-- https://mvnrepository.com/artifact/org.antlr/antlr4 -->
    <dependency>
        <groupId>org.antlr</groupId>
        <artifactId>antlr4-runtime</artifactId>
        <version>4.6</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.antlr</groupId>
            <artifactId>antlr4-maven-plugin</artifactId>
            <version>4.6</version>
            <configuration>
                <grammars>Java.g4</grammars>
                <visitor>true</visitor>
                <listener>true</listener>
                <inputEncoding>UTF-8</inputEncoding>
                <outputDirectory>${project.build.directory}/generated-sources/antlr4</outputDirectory>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>antlr4</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <source>${maven.compiler.source}</source>
                <target>${maven.compiler.target}</target>
            </configuration>
        </plugin>
    </plugins>
</build>

Step4: Executed the following maven goal to generate Visitor and Listener classes. Step4:执行以下maven目标来生成Visitor和Listener类。

org.antlr:antlr4-maven-plugin:4.6:antlr4

With all the files in place, I was able to write my parser easily.有了所有文件,我就可以轻松地编写解析器了。

EuReKA!!!

I know this is an old post but I found it because I had the same problem.我知道这是一篇旧帖子,但我找到了它,因为我遇到了同样的问题。 I re-generated my parser class while making sure the '-visitor' switch was in the command line.我重新生成了我的解析器类,同时确保“-visitor”开关在命令行中。 Dropping only the parser class into the existing project fixed the issue.将解析器类放入现有项目即可解决此问题。

By default, ANTLR generates listeners and does not generate visitors.默认情况下,ANTLR 生成侦听器,不生成访问者。

If you are using the ANTLR 4 tool in Eclipse, you should open Project properties, select ANTLR 4 / Tool and check the "Generate parse tree visitors (-visitor)" option.如果您在 Eclipse 中使用 ANTLR 4 工具,您应该打开项目属性,选择 ANTLR 4 / 工具并选中“生成解析树访问者 (-visitor)”选项。 You may need to touch (edit) the grammar file to force the ANTLR 4 tool to re-generate the sources.您可能需要触摸(编辑)语法文件以强制 ANTLR 4 工具重新生成源代码。

If you use maven, you should explicitly enable visitor generation:如果您使用 maven,您应该明确启用访问者生成:

<plugin>
  <groupId>org.antlr</groupId>
  <artifactId>antlr4-maven-plugin</artifactId>
  <version>${antlr.version}</version>
  <configuration>
      <listener>false</listener>
      <visitor>true</visitor>
  </configuration>
  <executions>
      <execution>
          <goals>
              <goal>antlr4</goal>
          </goals>
      </execution>
  </executions>
</plugin>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM