2013-02-27 62 views
1

我們正在開發一個DSL,我們正在面臨的一些問題:優先在ANTLR的使用括號

問題1:
在我們的DSL,它允許這樣做:
A + B + C

但不是這樣:
A + B - C

如果用戶需要使用兩個或多個不同的運營商,他需要插入圓括號:
A + (B - C)

(A + B) - C

問題2: 在我們的DSL中,最先例的運算符必須用圓括號包圍。

例如,而不是使用這種方式: A + B * C

的用戶需要使用這樣的: A + (B * C)

爲了解決這個問題我有ANTLR的片段,工作,但我不知道,如果是解決這個問題的最好辦法:

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; 

爲了解決這個問題,我不知道從哪裏開始。

我很感謝您的幫助,以找到解決第一個問題的更好的解決方案和解決第二個問題的方向。 (對不起我的英文不好)

下面是我們開發的語法:我認爲以下應工作

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();} 
; 

回答

2

這類似於根本沒有運算符優先級。

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

要處理**問題2 **您可以修改'expr'使其具有'scope'並設置使用的操作符的優先順序。在'atom'中,你可以引用'scope'並確保parens中的任何東西具有相同或更高的優先級。您也可以在'expr'規則中驗證這一點,以確保第一個'funcExpr'的優先級高於或等於'()*'子規則中使用的運算符。 – monty0 2013-03-02 05:56:05

0

。我假設一些名字明確的詞法分析器。

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 

唯一*規則匹配的表達,如果它僅具有括號外的一種類型的操作員的。 * Expr規則將匹配適當類型的運算符的行或轉到下一個運算符。

如果您有多種類型的運算符,則它們被強制置於圓括號內,因爲匹配將通過原子。