2014-01-14 56 views
0

我要創建語法識別這樣的:如果兩個表達式等於執行ifequal構建語法實施

ifequal(exp1, exp2) 
    statement1 
smaller 
    statement2 
larger 
    statement3 

語句1,第二如果第一較小第三如果是較大的。我試圖做出類似this解決方案,但沒有運氣。我不能使用優先順序,所以必須正確地更改語法。我正在使用杯子工具來生成解析器。

編輯:越來越大的部分是可選的。

回答

1

這是古代懸而未決(如果沒有別的)問題。如果您編寫一些代碼,如

if (a == b) then 
    if (b == c) then 
     do_something; 
    else 
     do_something_else; 

解析器在決定「其他」屬於哪個「if」時會出現問題。 一個解決方案是添加一個分隔符,如「endif」。例如:

if (a == b) then 
    if (b == c) then 
     do_something; 
    endif; 
    else 
     do_something_else; 
endif; 

不再被縮進混淆(我故意做錯了),現在很清楚該怎麼做。

這就是爲什麼像下面列出不起作用的一個語法(它產生了很多衝突):

stmtlist: stmt 
    | stmtlist stmt 

stmt: ifequal 
    | something_else 

ifequal: IFEQUAL '(' expr ',' expr ')' stmtlist opt_lt_gt 

opt_lt_gt: 
    | SMALLER stmtlist 
    | LARGER stmtlist 
    | SMALLER stmtlist LARGER stmtlist 

但只要語句列表以某種方式從IFEQUAL聲明,例如分離通過使用大括號,問題就消失了。

stmtlist: '{' stmtseq '}' 

stmtseq: stmt 
    | stmtseq stmt 

另一種可能性是禁止stmtlist中的不完整的語句。這會或多或少地加倍你的語法。它可能看起來像

fullifequal: IFEQUAL '(' expr ',' expr ')' fstmtlist SMALLER fstmtlist LARGER fstmtlist 

fstmtlist: fullstmt 
    |  fstmtlist fullstmt 

fullstmt: fullifequal 
    |  some_other 

ifequal: IFEQUAL '(' expr ',' expr ')' fstmtlist opt_lt_gt 

opt_lt_gt: 
    |  SMALLER fstmtlist 
    |  LARGER fstmtlist 
    |  SMALLER fstmtlist LARGER fstmtlist 

個人而言,我更喜歡在大括號解決方案,因爲它很容易閱讀,不限制的「ifequal」語句和解析器代碼中的語句會更短。但我想你會需要另一種解決方案。