Antlr 使用带有布尔检查的树遍历器+;捕捉整个表情

Antlr 使用带有布尔检查的树遍历器+;捕捉整个表情,antlr,antlr3,Antlr,Antlr3,实际上,我有两个问题,我希望能得到回答,因为它们半依赖于我的工作。下面是语法+树语法+Java测试文件 我实际上试图实现以下目标: 问题1: grammar Test; options { language = Java; output = AST; } parse : varDeclare+ ; varDeclare : type id equalExp? ';' ; equalExp : ('=' (expression | '...'))

实际上,我有两个问题,我希望能得到回答,因为它们半依赖于我的工作。下面是语法+树语法+Java测试文件

我实际上试图实现以下目标:

问题1:

grammar Test;
options {
  language = Java;
  output = AST;
}

parse : varDeclare+
      ;

varDeclare : type id equalExp? ';'
           ;

equalExp : ('=' (expression | '...'))
         ;

expression : binaryExpression
           ;

binaryExpression : addingExpression (('=='|'!='|'<='|'>='|'>'|'<') addingExpression)*
                 ;

addingExpression : multiplyingExpression (('+'|'-') multiplyingExpression)*
                 ;

multiplyingExpression : unaryExpression 
                        (('*'|'/') unaryExpression)*
                      ;

unaryExpression: ('!'|'-')* primitiveElement;   

primitiveElement : literalExpression
                 | id
                 | '(' expression ')'
                 ;  

literalExpression : INT
                  ;              

id : IDENTIFIER
   ;

type : 'int'    
     | 'float'
     ; 

// L E X I C A L   R U L E S      

INT : DIGITS ;   

IDENTIFIER : LETTER (LETTER | DIGIT)*;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

fragment LETTER : ('a'..'z' | 'A'..'Z' | '_') ;
fragment DIGITS: DIGIT+;
fragment DIGIT : '0'..'9';
tree grammar TestTree;

options {
  language = Java;
  tokenVocab = Test;
  ASTLabelType = CommonTree;
}

@members {
    SemanticCheck s;

    public TestTree(TreeNodeStream input, SemanticCheck s) {
        this(input);
        this.s = s;
    }

}

parse[SemanticCheck s]
      : varDeclare+
      ;

varDeclare : type id equalExp? ';'
           {s.check($type.name, $id.text, $equalExp.expr);}
           ;

equalExp returns [String expr]
         : ('=' (expression {$expr = $expression.e;} | '...' {$expr = "...";}))
         ;

expression returns [String e]
@after {$e = $expression.text;}
           : binaryExpression
           ;

binaryExpression : addingExpression (('=='|'!='|'<='|'>='|'>'|'<') addingExpression)*
                 ;

addingExpression : multiplyingExpression (('+'|'-') multiplyingExpression)*
                 ;

multiplyingExpression : unaryExpression 
                        (('*'|'/') unaryExpression)*
                      ;

unaryExpression: ('!'|'-')* primitiveElement;   

primitiveElement : literalExpression
                 | id
                 | '(' expression ')'
                 ;  

literalExpression : INT
                  ;              

id : IDENTIFIER
   ;

type returns [String name]
@after { $name = $type.text; }
     : 'int'    
     | 'float'
     ; 
import java.util.ArrayList;
import java.util.List;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RuleReturnScope;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;

public class Test {
    public static void main(String[] args) throws Exception {
        SemanticCheck s = new SemanticCheck();

        String src = 
                "float x = 10+y; \n" + 
                "float x; \n";
        TestLexer lexer = new TestLexer(new ANTLRStringStream(src));
        //TestLexer lexer = new TestLexer(new ANTLRFileStream("input.txt"));
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        TestParser parser = new TestParser(tokenStream);
        RuleReturnScope r = parser.parse();

        System.out.println("Parse Tree:\n" + tokenStream.toString());

        CommonTree t = (CommonTree)r.getTree();
        CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
        nodes.setTokenStream(tokenStream);

        TestTree walker = new TestTree(nodes, s);
        walker.parse(s);

    }
}

class SemanticCheck {
    List<String> names;

    public SemanticCheck() {
        this.names = new ArrayList<String>();

    }

    public boolean check(String type, String variableName, String exp) {
        System.out.println("Type: " + type + "  variableName: " + variableName + "  exp: " + exp);
        if(names.contains(variableName)) {
            System.out.println("Remove statement! Already defined!");
            return true;
        }

        names.add(variableName);
        return false;
    }
}
Tree:(VARDECL float x (= 10)) (VARDECL int x (= 1))

Type: float  variableName: x  exp: = 10
Type: int  variableName: x  exp: = 1

Tree Walker: (VARDECL float x (= 10)) REMOVED
我有一个语法可以正确解析我的语言。我想对变量声明进行一些语义检查。所以我创造了一个树行者,到目前为止它还可以工作。我的问题是它没有捕获整个表达式字符串。比如说,

float x = 10 + 10;
它只捕获第一部分,即10。我不确定我做错了什么。如果我一次就做到了,它就行了。不知何故,如果我将工作分为语法和树语法,它就不能捕获整个字符串

问题2:

grammar Test;
options {
  language = Java;
  output = AST;
}

parse : varDeclare+
      ;

varDeclare : type id equalExp? ';'
           ;

equalExp : ('=' (expression | '...'))
         ;

expression : binaryExpression
           ;

binaryExpression : addingExpression (('=='|'!='|'<='|'>='|'>'|'<') addingExpression)*
                 ;

addingExpression : multiplyingExpression (('+'|'-') multiplyingExpression)*
                 ;

multiplyingExpression : unaryExpression 
                        (('*'|'/') unaryExpression)*
                      ;

unaryExpression: ('!'|'-')* primitiveElement;   

primitiveElement : literalExpression
                 | id
                 | '(' expression ')'
                 ;  

literalExpression : INT
                  ;              

id : IDENTIFIER
   ;

type : 'int'    
     | 'float'
     ; 

// L E X I C A L   R U L E S      

INT : DIGITS ;   

IDENTIFIER : LETTER (LETTER | DIGIT)*;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

fragment LETTER : ('a'..'z' | 'A'..'Z' | '_') ;
fragment DIGITS: DIGIT+;
fragment DIGIT : '0'..'9';
tree grammar TestTree;

options {
  language = Java;
  tokenVocab = Test;
  ASTLabelType = CommonTree;
}

@members {
    SemanticCheck s;

    public TestTree(TreeNodeStream input, SemanticCheck s) {
        this(input);
        this.s = s;
    }

}

parse[SemanticCheck s]
      : varDeclare+
      ;

varDeclare : type id equalExp? ';'
           {s.check($type.name, $id.text, $equalExp.expr);}
           ;

equalExp returns [String expr]
         : ('=' (expression {$expr = $expression.e;} | '...' {$expr = "...";}))
         ;

expression returns [String e]
@after {$e = $expression.text;}
           : binaryExpression
           ;

binaryExpression : addingExpression (('=='|'!='|'<='|'>='|'>'|'<') addingExpression)*
                 ;

addingExpression : multiplyingExpression (('+'|'-') multiplyingExpression)*
                 ;

multiplyingExpression : unaryExpression 
                        (('*'|'/') unaryExpression)*
                      ;

unaryExpression: ('!'|'-')* primitiveElement;   

primitiveElement : literalExpression
                 | id
                 | '(' expression ')'
                 ;  

literalExpression : INT
                  ;              

id : IDENTIFIER
   ;

type returns [String name]
@after { $name = $type.text; }
     : 'int'    
     | 'float'
     ; 
import java.util.ArrayList;
import java.util.List;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RuleReturnScope;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;

public class Test {
    public static void main(String[] args) throws Exception {
        SemanticCheck s = new SemanticCheck();

        String src = 
                "float x = 10+y; \n" + 
                "float x; \n";
        TestLexer lexer = new TestLexer(new ANTLRStringStream(src));
        //TestLexer lexer = new TestLexer(new ANTLRFileStream("input.txt"));
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        TestParser parser = new TestParser(tokenStream);
        RuleReturnScope r = parser.parse();

        System.out.println("Parse Tree:\n" + tokenStream.toString());

        CommonTree t = (CommonTree)r.getTree();
        CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
        nodes.setTokenStream(tokenStream);

        TestTree walker = new TestTree(nodes, s);
        walker.parse(s);

    }
}

class SemanticCheck {
    List<String> names;

    public SemanticCheck() {
        this.names = new ArrayList<String>();

    }

    public boolean check(String type, String variableName, String exp) {
        System.out.println("Type: " + type + "  variableName: " + variableName + "  exp: " + exp);
        if(names.contains(variableName)) {
            System.out.println("Remove statement! Already defined!");
            return true;
        }

        names.add(variableName);
        return false;
    }
}
Tree:(VARDECL float x (= 10)) (VARDECL int x (= 1))

Type: float  variableName: x  exp: = 10
Type: int  variableName: x  exp: = 1

Tree Walker: (VARDECL float x (= 10)) REMOVED
我想检查一个规则,如果我的条件返回true,我想删除那个子树。比如说,

float x = 10;
float x; // <================ I would like this to be removed.
float x=10;

浮点x;// 我解决了我的问题,结果发现我需要先构建一个AST,然后才能做任何事情。这将有助于理解扁平树与构建AST的区别

多亏了StackOverFlow中的无数示例,我能够使用语义谓词来完成上面示例中需要的工作

更新代码如下:

测试.g

 grammar Test;
    options {
      language = Java;
      output = AST;
    }
    tokens {
    VARDECL;
    Assign = '=';
    EqT    = '==';  
    NEq    = '!=';
    LT     = '<';
    LTEq   = '<=';
    GT     = '>';
    GTEq   = '>=';
    NOT    = '!';
    PLUS   = '+';
    MINUS  = '-';
    MULT   = '*';
    DIV    = '/';
    }

    parse : varDeclare+
          ;

    varDeclare : type id equalExp ';' -> ^(VARDECL type id equalExp)
               ;

    equalExp : (Assign^ (expression | '...' )) 
             ;

    expression : binaryExpression
               ;

    binaryExpression : addingExpression ((EqT|NEq|LTEq|GTEq|LT|GT)^ addingExpression)*
                     ;

    addingExpression : multiplyingExpression ((PLUS|MINUS)^ multiplyingExpression)*
                     ;

    multiplyingExpression : unaryExpression 
                            ((MULT|DIV)^ unaryExpression)*
                          ;

    unaryExpression: ((NOT|MINUS))^ primitiveElement
                   | primitiveElement
                   ;   

    primitiveElement : literalExpression
                     | id
                     | '(' expression ')' -> expression
                     ;  

    literalExpression : INT
                      ;              

    id : IDENTIFIER
       ;

    type : 'int'    
         | 'float'
         ; 

    // L E X I C A L   R U L E S      

    INT : DIGITS ;   

    IDENTIFIER : LETTER (LETTER | DIGIT)*;

    WS  :   ( ' '
            | '\t'
            | '\r'
            | '\n'
            ) {$channel=HIDDEN;}
        ;

    fragment LETTER : ('a'..'z' | 'A'..'Z' | '_') ;
    fragment DIGITS: DIGIT+;
    fragment DIGIT : '0'..'9';
tree grammar TestTree;

options {
  language = Java;
  tokenVocab = Test;
  ASTLabelType = CommonTree;
  output = AST;
}

tokens {
    REMOVED;
}

@members {
    SemanticCheck s;

    public TestTree(TreeNodeStream input, SemanticCheck s) {
        this(input);
        this.s = s;
    }

}

start[SemanticCheck s] : varDeclare+
      ;

varDeclare : ^(VARDECL type id equalExp)
            -> {s.check($type.text, $id.text, $equalExp.text)}? REMOVED
            -> ^(VARDECL type id equalExp)  
           ;

equalExp : ^(Assign expression)
         | ^(Assign '...')
         ;

expression : ^(('!') expression)
        | ^(('+'|'-'|'*'|'/') expression expression*)
        | ^(('=='|'<='|'<'|'>='|'>'|'!=') expression expression*)
        | literalExpression
       ;                                  

literalExpression : INT
                  | id
                  ;  

id : IDENTIFIER
   ;

type : 'int'    
     | 'float'
     ; 

希望这有帮助!如果我做错了什么,请随时指出任何错误。

我似乎知道我哪里做错了,在进行任何树语法遍历之前,我需要先构建一个有效的AST。稍后我会发布一个答案。同时,如何编辑用带有树语法的语法创建的“第一棵”树?我不想将AST从树语法传递到下一个。我希望这是有道理的。我也想到了上面的评论。重写=真;在选项中,我会做我想做的事情。