2012-03-01 143 views
1

我正在使用ANTLR创建和/或解析器+评估器。表达式将会有这样的格式:antlr解析器和/或逻辑 - 如何获得逻辑运算符之间的表达式?

  • x eq 1 && y eq 10
  • (x lt 10 && x gt 1) OR x eq -1

我正在读的逻辑表达式这个帖子在ANTLR Looking for advice on project. Parsing logical expression,我发现语法贴有一个良好的开端:

grammar Logic; 

parse 
    : expression EOF 
    ; 

expression 
    : implication 
    ; 

implication 
    : or ('->' or)* 
    ; 

or 
    : and ('&&' and)* 
    ; 

and 
    : not ('||' not)* 
    ; 

not 
    : '~' atom 
    | atom 
    ; 

atom 
    : ID 
    | '(' expression ')' 
    ; 

ID : ('a'..'z' | 'A'..'Z')+; 
Space : (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;}; 

但是,虽然从解析器中获取树对于变量只是表达式一个字符(即,"(A || B) AND C",我很难适应这种情况(例如"x eq 1 && y eq 10"我期望一个"AND"父母和两个孩子,"x eq 1""y eq 10",请参阅下面的测试用例)。我想这与"ID"有关。正确的语法是什么?

+0

在这里发布,以及:HTTP://antlr.markmail。org/message/bk6kutcu56vuglgl – 2012-03-01 18:52:09

回答

2

对于那些有兴趣,我改变了我的语法文件的一些改进(参见下文)

电流限制:

  • 只适用于& &/||,而不是AND/OR(不是很有问题的)

  • 你不能有括号和& &/||之间的空间(我解决了这个问题,在输入词法分析器之前,用源代码字符串中的“)”替换“(”,“)”和“)”,

    语法逻辑;

    options { 
        output = AST; 
    } 
    
    tokens { 
        AND = '&&'; 
        OR = '||'; 
        NOT = '~'; 
    } 
    
    // parser/production rules start with a lower case letter 
    parse 
        : expression EOF! // omit the EOF token 
        ; 
    
    expression 
        : or 
        ; 
    
    or 
        : and (OR^ and)* // make `||` the root 
        ; 
    
    and 
        : not (AND^ not)*  // make `&&` the root 
        ; 
    
    not 
        : NOT^ atom // make `~` the root 
        | atom 
        ; 
    
    atom 
        : ID 
        | '('! expression ')'! // omit both `(` and `)` 
        ; 
    
    // lexer/terminal rules start with an upper case letter 
    ID 
        : 
        (
        'a'..'z' 
        | 'A'..'Z' 
        | '0'..'9' | ' ' 
        | SYMBOL 
    )+ 
        ; 
    
    SYMBOL 
        : 
        ('+'|'-'|'*'|'/'|'_') 
    ; 
    
0
ID : ('a'..'z' | 'A'..'Z')+; 

指出标识符是一个或多个字母的序列,但不允许任何数字。尝试

ID : ('a'..'z' | 'A'..'Z' | '0'..'9')+; 

这将允许例如, abc,123,12abab12。如果你不想要后者,你必须重新调整规则(留作挑战...)

为了接受任意多个标识符,你可以将​​定义为ID+而不是ID

此外,你可能会需要指定ANDOR->~作为标记,以便作为@Bart煮布锅说,前两个不会得到列为ID,所以后两者将得到认可在所有。

+0

@Aasmund,这并没有考虑我认为的两件事:一个令牌可以有空格(“绿色neq绿色”应该是一个令牌)的事实。此外,使用AND/OR而不是&&/||,不应该在ID中说出类似〜和&&〜或(或〜“AND”,〜“OR”)的内容吗? – mmalmeida 2012-03-01 09:39:08

+0

@wild_oscar:我没有明白。看到我更新的答案。 – 2012-03-01 11:58:29

+0

@AasmundEldhuset:如果您将原子更改为ID +,但不向ID添加“|''”,是不是说您期望IDID ... ID,即1eq1(不含空格)?该语法标记1 eq 1 || B转换成父母||和4个孩子(1,eq,1,B),而不是2个孩子(1 eq 1,B)。 – mmalmeida 2012-03-01 14:30:21