2017-01-24 19 views
1

我仍然是ANTLR的新手,所以如果我發佈一個明顯的問題,非常抱歉。如何在語法中表達所需的「返回」語句

我有一個相對簡單的語法。我需要的是用戶能夠輸入類似以下:

if (condition) 
{ 
    return true 
} 
else if (condition) 
{ 
    return false 
} 
else 
{ 
    if (condition) 
    { 
     return true 
    } 
    return false 
} 

在下面我的語法,是有辦法,以確保如果輸入字符串不包含一個錯誤將被標記'返回'聲明?如果沒有,我可以通過聽衆來做到,如果是的話,怎麼辦?

grammar Evaluator; 

parse 
: block EOF 
; 

block 
: statement 
; 

statement 
: return_statement 
| if_statement 
; 

return_statement 
: RETURN (TRUE | FALSE) 
; 

if_statement 
: IF condition_block (ELSE IF condition_block)* (ELSE statement_block)? 
; 

condition_block 
: expression statement_block 
; 

statement_block 
: OBRACE block CBRACE 
; 

expression 
: MINUS expression         #unaryMinusExpression 
| NOT expression         #notExpression 
| expression op=(MULT | DIV) expression    #multiplicationExpression 
| expression op=(PLUS | MINUS) expression   #additiveExpression 
| expression op=(LTEQ | GTEQ | LT | GT) expression #relationalExpression 
| expression op=(EQ | NEQ) expression    #equalityExpression 
| expression AND expression       #andExpression 
| expression OR expression       #orExpression 
| atom            #atomExpression 
; 

atom 
: function             #functionAtom 
| OPAR expression CPAR          #parenExpression 
| (INT | FLOAT)           #numberAtom 
| (TRUE | FALSE)           #booleanAtom 
| ID              #idAtom 
; 

function 
: ID OPAR (parameter (',' parameter)*)? CPAR 
; 

parameter 
: expression            #expressionParameter 
; 

OR : '||'; 
AND : '&&'; 
EQ : '=='; 
NEQ : '!='; 
GT : '>'; 
LT : '<'; 
GTEQ : '>='; 
LTEQ : '<='; 
PLUS : '+'; 
MINUS : '-'; 
MULT : '*'; 
DIV : '/'; 
NOT : '!'; 
OPAR : '('; 
CPAR : ')'; 
OBRACE : '{'; 
CBRACE : '}'; 
ASSIGN : '='; 

RETURN : 'return'; 
TRUE : 'true'; 
FALSE : 'false'; 
IF : 'if'; 
ELSE : 'else'; 

// ID either starts with a letter then followed by any number of a-zA-Z_0-9 
// or starts with one or more numbers, then followed by at least one a-zA-Z_ then followed 
// by any number of a-zA-Z_0-9 

ID 
: [a-zA-Z] [a-zA-Z_0-9]* 
| [0-9]+ [a-zA-Z_]+ [a-zA-Z_0-9]* 
; 

INT 
: [0-9]+ 
; 

FLOAT 
: [0-9]+ '.' [0-9]* 
| '.' [0-9]+ 
; 

SPACE 
: [ \t\r\n] -> skip 
; 

// Anything not recognized above will be an error 
ErrChar 
    : . 
    ; 

回答

0

羅斯的回答是完全正確的。你設計你的語法來接受某個輸入。如果輸入流不一致,解析器將會投訴。

讓我重寫你的語法是這樣的:

grammar Question; 

/* enforce each block to end with a return statement */ 

a_grammar 
    : if_statement EOF 
    ; 

if_statement 
    : 'if' expression statement+ ('else' statement+)? 
    ; 

statement 
    : if_statement 
// other statements 
    | statement_block 
    ; 

statement_block 
    : '{' statement* return_statement '}' 
    ; 

return_statement 
    : 'return' ('true' | 'false') 
    ; 

expression // reduced to a strict minimum to answer the OP question 
    : atom 
    | atom '<=' atom 
    | '(' expression ')' 
    ; 

atom 
    : ID 
    | INT 
    ; 

ID 
    : [a-zA-Z] [a-zA-Z_0-9]* 
    | [0-9]+ [a-zA-Z_]+ [a-zA-Z_0-9]* 
    ; 

INT : [0-9]+ ; 
WS : [ \t\r\n] -> skip ; 

// Anything not recognized above will be an error 
ErrChar 
    : . 
    ; 

用下面的輸入

if (a <= 7) 
    { 
     return true 
    } 
else 
    if (xyz <= 99) 
    { 
     return false 
    } 
    else [email protected]#!$rect 
    { 
     if (b <= a) 
     { 
      return true 
     } 
     return false 
    } 

你得到這些令牌

[@0,0:1='if',<'if'>,1:0] 
[@1,3:3='(',<'('>,1:3] 
[@2,4:4='a',<ID>,1:4] 
[@3,6:7='<=',<'<='>,1:6] 
... 
[@21,82:85='else',<'else'>,10:1] 
[@22,87:91='incor',<ID>,10:6] 
[@23,92:92='@',<ErrChar>,10:11] 
[@24,93:93='#',<ErrChar>,10:12] 
[@25,94:94='!',<ErrChar>,10:13] 
[@26,95:95='$',<ErrChar>,10:14] 
[@27,96:99='rect',<ID>,10:15] 
[@28,102:102='{',<'{'>,11:1] 
... 
line 10:6 mismatched input 'incor' expecting {'if', '{'} 

如果與運行試驗檯-gui選項,它會顯示帶有錯誤標記的解析樹,並且顯示爲粉紅色!

grun Question a_grammar -gui data.txt 
0

我從來沒有玩過Listener。 通過訪問者,在VisitStatement(StatementContext上下文)方法中,檢查context.return_statement()(ReturnStatementContext)是否爲空。如果它爲null,則拋出異常。

+0

對於我的情況,訪客太晚了。我有一個編輯器在調用Visit之前使用Parser來檢查語法。如果語法錯誤,我們向用戶顯示錯誤(行和列)。 – XBond

0

我也是新手。我想迫使詞法分析器BARF由 需要return語句,所以不是:

statement 
: return_statement 
| if_statement 
; 

哪一個語句可以是一個if_statement或return_statement我會嘗試這樣的:

statement 
: (if_statement)? return_statement 
; 

哪(我相信),說if_statement是可選的,但return_statement必須總是發生。但你可能想嘗試類似於:

block_data : statements+ return_statement; 

其中語句可以是if_statements等,並且其中一個或多個是允許的。

因爲我一個星期左右一直在與ANTLR4一起工作,所以我會採取一切措施。我有4個.g4文件的工作,並很高興與ANTLR,但你實際上可能有更多的ANTLR棒的時間比我

-Regards