【问题标题】:Antlr 4 deactivate a subrule within a left-recursive ruleAntlr 4 停用左递归规则中的子规则
【发布时间】:2013-09-05 01:53:30
【问题描述】:

我正在为prolog编写一个解析器,以下是源代码的一部分。 "arg_term" 和 "term" 很相似,但是不能匹配 ',' 表达式,因为我需要统计参数的个数。 "arg_item" 需要匹配 ',' 表达式,所以我创建了两个类似的规则。我尝试使用语义谓词,但 Antlr 4 报告编译错误。现在它似乎不支持直接左递归规则中的语义谓词。实现看起来很笨拙。谁能提供更好的解决方案?

我对 Antlr 和编译器的实现不是很熟悉。在 prolog 中,用户可以定义自己的操作符和相关的优先级。如何应对此类情况?现在我只是忽略它们的优先级并将它们放在“术语”规则的末尾。

arguments returns [ int argc ]  //return argument number
    : 
    arg {$argc = 1; } (',' arg {$argc = $argc + 1;} )*  
    ;

arg :
    arg_term
    | '(' arg_item  ')'
    | '{' arg_item '}' 
    ;

arg_item:
     ':-' term
      | term ':-' term
      | term
        ;

arg_term :
    simple_term
    |'(' arg_term ')'
    | ('+'|'-') arg_term    //here '+, -' denotes number's sign.
    | arg_term ('**'|'^'|'isa'|'has')  arg_term        
    | arg_term ('//' | 'mod' | 'rem'  | '<<' | '>>' |'*' |'/')  arg_term     
    | arg_term ('+'|'-'|'#')  arg_term           
    | arg_term ':' arg_term                       
    | arg_term (OP_XFY_700|'<'|'>'|'=')  arg_term
    | '\\+' arg_term        
    | arg_term '->' arg_term 
    | arg_term ';' arg_term 
    | OP_FX_1150 arg_term
    | arg_term user_op arg_term 
    ;

term
    : 
    simple_term
    |'(' term ')'
    | ('+'|'-') term    
    | term ('**'|'^'|'isa'|'has')  term        
    | term ('//' | 'mod' | 'rem'  | '<<' | '>>' |'*' |'/')  term     
    | term ('+'|'-'|'#')  term           
    | term ':' term                      
    | term (OP_XFY_700|'<'|'>'|'=')  term
    | '\\+' term        
    | term ',' term     
    | term '->' term 
    | term ';' term 
    | OP_FX_1150 term
    | term user_op term 
    ;

【问题讨论】:

    标签: dynamic semantics predicate antlr4 operator-precedence


    【解决方案1】:

    1) 自 v3 以来,ANTLR4 中的语义谓词发生了变化(请参阅 here)。

    2) 要清理您的 arg_termterm 产生式,请尝试类似于以下语法 sn-p 的内容:

    grammar Prolog;
    
    ...
    
    argTerm: term (',' term)*;
    
    term :
        simpleTerm
        |'(' term ')'
        | ('+'|'-') term
        | term ('**'|'^'|'isa'|'has')  term        
        | term ('//' | 'mod' | 'rem'  | '<<' | '>>' |'*' |'/') term     
        | term ('+'|'-'|'#') term           
        | term ':' term                       
        | term (OP_XFY_700|'<'|'>'|'=')  term
        | '\\+' term        
        | term '->' term 
        | term ';' term 
        | OP_FX_1150 term
        | term user_op term 
        ;
    
    ...
    

    3) 使用 ANTLR4 生成的ParseTreeVisitor,而不是将该 Java 代码嵌入到您的语法中。

    您可以使用命令行中的 -visitor 参数生成 PrologBaseVisitor:

    org.antlr.v4.Tool -visitor Prolog.g4
    

    这是一个扩展生成的 PrologBaseVisitor 的实现示例,它将计算您的参数:

    public class ProglogArgCountVis extends PrologBaseVisitor<Integer> {
    
        // By default, all productions will return 0.
        @Override
        protected Integer defaultResult() {
             return 0;
        }
    
        // Return the size of ctx.term(), which is a list of 
        // TermContexts... see generated parser code.
        @Override
        public Integer visitArgTermContext(ArgTermContext ctx) {
             return ctx.term().size();
        }
    
    }
    

    使用这个访问者看起来像这样:

    PrologParser p;
    
    ....
    
    Integer argCount = new PrologArgCountVis().visit(p.argTerm());
    

    实现用户定义的优先级会很有趣。我认为处理这种情况的最好方法是定义另一个 PrologBaseVisitor,让它检查它访问的每个运算符的优先级并进行相应的评估。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多