3

我正在为 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 
    ;
4

1 回答 1

0

1) ANTLR4 中的语义谓词自 v3 以来发生了变化(请参见此处)。

2)要清理您的arg_termterm作品,请尝试类似于以下语法片段的内容:

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)与其在语法中嵌入 Java 代码,不如使用 ANTLR4 生成的ParseTreeVisitor

-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,让它检查它访问的每个运算符的优先级并进行相应的评估。

于 2014-09-23T12:57:41.563 回答