【问题标题】:Precedence in Antlr using parenthesesAntlr 中使用括号的优先级
【发布时间】:2013-02-27 14:14:46
【问题描述】:

我们正在开发 DSL,但我们面临一些问题:

问题 1:
在我们的 DSL 中,允许这样做:
A + B + C

但不是这个:
A + B - C

如果用户需要使用两个或更多不同的运算符,他需要插入括号:
A + (B - C)

(A + B) - C

问题 2: 在我们的 DSL 中,最先例的运算符必须用括号括起来。

例如,不要使用这种方式: A + B * C

用户需要使用这个: A + (B * C)

为了解决问题1,我有一个有效的ANTLR sn-p,但我不确定它是否是解决它的最佳方法:

sumExpr
@init {boolean isSum=false;boolean isSub=false;}
    : {isSum(input.LT(2).getText()) && !isSub}? multExpr('+'^{isSum=true;} sumExpr)+
    | {isSub(input.LT(2).getText()) && !isSum}? multExpr('-'^{isSub=true;} sumExpr)+
    | multExpr;

要解决问题2,我不知道从哪里开始。

感谢您帮助找出第一个问题的更好解决方案和解决第二个问题的方向。 (对不起我的英语不好)

以下是我们开发的语法:

grammar TclGrammar;

options {
    output=AST;
    ASTLabelType=CommonTree;
}

@members {
    public boolean isSum(String type) {
    System.out.println("Tipo: " + type);
    return "+".equals(type);
}

public boolean isSub(String type) {
    System.out.println("Tipo: " + type);
    return "-".equals(type);
}
}

prog    
: exprMain ';' {System.out.println( 
    $exprMain.tree == null ? "null" : $exprMain.tree.toStringTree());}
;

exprMain
:   exprQuando? (exprDeveSatis | exprDeveFalharCaso)
;

exprDeveSatis
: 'DEVE SATISFAZER' '{'! expr '}'!
;

exprDeveFalharCaso
: 'DEVE FALHAR CASO' '{'! expr '}'! 
;

exprQuando
: 'QUANDO' '{'! expr '}'!
;

expr    
: logicExpr
;

logicExpr
:   boolExpr (('E'|'OU')^ boolExpr)*
;

boolExpr
: comparatorExpr
| emExpr
| 'VERDADE'
| 'FALSO'
;

emExpr
: FIELD 'EM' '[' (variable_lista | field_lista) comCruzamentoExpr? ']'
-> ^('EM' FIELD (variable_lista+)? (field_lista+)? comCruzamentoExpr?)
;

comCruzamentoExpr
: 'COM CRUZAMENTO' '('  FIELD ';' FIELD (';' FIELD)* ')' -> ^('COM CRUZAMENTO' FIELD+)
;

comparatorExpr
: sumExpr (('<'^|'<='^|'>'^|'>='^|'='^|'<>'^) sumExpr)?
| naoPreenchidoExpr
| preenchidoExpr
;

naoPreenchidoExpr
: FIELD 'NAO PREENCHIDO' -> ^('NAO PREENCHIDO' FIELD)
;

preenchidoExpr
: FIELD 'PREENCHIDO' -> ^('PREENCHIDO' FIELD)
;

sumExpr
@init {boolean isSum=false;boolean isSub=false;}
: {isSum(input.LT(2).getText()) && !isSub}? multExpr('+'^{isSum=true;} sumExpr)+
| {isSub(input.LT(2).getText()) && !isSum}? multExpr('-'^{isSub=true;} sumExpr)+
| multExpr
;

multExpr
: funcExpr(('*'^|'/'^) funcExpr)?
;

funcExpr
: 'QUANTIDADE'^ '('! FIELD ')'!
| 'EXTRAI_TEXTO'^ '('! FIELD ';' INTEGER ';' INTEGER ')'! 
| cruzaExpr
| 'COMBINACAO_UNICA' '(' FIELD ';' FIELD (';' FIELD)* ')' -> ^('COMBINACAO_UNICA' FIELD+)
| 'EXISTE'^ '('! FIELD ')'!
| 'UNICO'^ '('! FIELD ')'!
| atom
;

cruzaExpr
:   operadorCruzaExpr ('CRUZA COM'^|'CRUZA AMBOS'^) operadorCruzaExpr ondeExpr?
;

operadorCruzaExpr
:   FIELD('('!field_lista')'!)?
;

ondeExpr
:   ('ONDE'^ '('!expr')'!)
;

atom
: FIELD 
| VARIABLE
| '('! expr ')'!
;

field_lista
: FIELD(';' field_lista)?
;

variable_lista
: VARIABLE(';' variable_lista)?
;

FIELD  
:   NONCONTROL_CHAR+
    ;

NUMBER
:   INTEGER | FLOAT
;

VARIABLE
: '\'' NONCONTROL_CHAR+ '\''
;

fragment SIGN: '+' | '-';   
fragment NONCONTROL_CHAR: LETTER | DIGIT | SYMBOL;
fragment LETTER: LOWER | UPPER;
fragment LOWER: 'a'..'z';
fragment UPPER: 'A'..'Z';
fragment DIGIT: '0'..'9';
fragment SYMBOL: '_' | '.' | ',';
fragment FLOAT: INTEGER '.' '0'..'9'*;
fragment INTEGER: '0' | SIGN? '1'..'9' '0'..'9'*;

WS  :   ( ' '
    | '\t'
    | '\r'
    | '\n'
    ) {skip();}
;

【问题讨论】:

    标签: antlr antlr3 lexer


    【解决方案1】:

    这类似于根本没有运算符优先级。

    expr
      : funcExpr
        ( ('+' funcExpr)*
        | ('-' funcExpr)*
        | ('*' funcExpr)*
        | ('/' funcExpr)*
        )
      ;
    

    【讨论】:

    • 要处理 问题 2,您可以将 expr 修改为 scope 并设置使用的运算符的优先级。在atom 中,您可以引用scope 并确保括号内的任何内容具有相同或更高的优先级。您还可以在expr 规则中验证这一点,以确保第一个funcExpr 的优先级高于或等于()* 子规则中使用的运算符。
    【解决方案2】:

    我认为以下应该可行。我假设一些词法分析器标记具有明显的名称。

    expr: sumExpr;
    
    sumExpr: onlySum | subExpr;
    
    onlySum: atom ( PLUS onlySum )?;
    
    subExpr: onlySub | multExpr;
    
    onlySub: atom ( MINUS onlySub )? ;
    
    multExpr: atom ( STAR atomic )? ;
    
    parenExpr: OPEN_PAREN expr CLOSE_PAREN;
    
    atom: FIELD | VARIABLE | parenExpr
    

    only* 规则匹配一个表达式,如果它在括号外只有一种类型的运算符。 *Expr 规则匹配具有适当类型运算符的行或转到下一个运算符。

    如果您有多种类型的运算符,那么它们将被强制放在括号内,因为匹配将通过原子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-01
      • 2012-12-16
      • 2012-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多