2014-09-19 22 views
0

我正在嘗試處理最終將使用類似柑橘類Ruby的語法中的語法的布爾邏輯。我得到一個遞歸問題,但我不清楚爲什麼。下面是我想要處理文本(它應該有在最後一個換行符):使用Citrus解析表達式語法時使用Citrus的堆棧級別太深

COMMANDWORD # MYCOMMENT 

這裏是我的柑橘語法(用來處理更高級的東西):

grammar Grammar 
    rule commandset 
    command+ 
    end 

    rule command 
    identifier command_detail* comment_to_eol* "\n" 
    end 

    rule command_detail 
    assign_expr | expr 
    end 

    rule assign_expr 
    identifier ":=" expr 
    end 

    rule expr 
    # Stack overflow 
    or_expr | gtor_expr 
    # No problem! 
    # or_expr 
    end 

    rule or_expr 
    # Temporarily match everything except a comment... 
    [^#]+ 
    # What I think will be correct in the future... 
    # gtor_expr "OR" expr 
    end 

    rule gtor_expr 
    and_expr | gtand_expr 
    end 

    rule and_expr 
    gtand_expr "AND" gtor_expr 
    end 

    rule gtand_expr 
    not_expr | gtnot_expr 
    end 

    rule not_expr 
    "NOT" gtnot_expr | gtand_expr 
    end 

    rule gtnot_expr 
    parens_expr | identifier 
    end 

    rule parens_expr 
    "(" expr ")" 
    end 

    rule identifier 
    ws* [a-zA-Z0-9]+ ws* 
    end 

    rule ws 
    [ ] 
    end 

    rule comment_to_eol 
    "#" [^\n]* 
    end 
end 

的重要的事情在規則expr和規則or_expr。我已經更改了or_expr,因此它匹配除註釋外的所有內容。如果我堅持使用當前的expr規則,我會發生堆棧溢出。但如果我切換它,所以它沒有or_expr和gtor_expr之間的選擇它工作正常。

我對「選擇」的理解是,它會嘗試按順序對它們進行評估。如果第一個選擇失敗,那麼它會嘗試第二個。在這種情況下,第一種選擇顯然能夠成功,那麼爲什麼如果我包含一個永遠不應該被採用的第二種選擇,爲什麼會出現堆棧溢出?

+1

乍一看,似乎在'gtor_expr'取決於'and_expr '這取決於'gtor_expr'。無限循環。 – 2014-09-19 21:00:03

+0

@MarkThomas我知道這似乎很奇怪。我將它從此處的算術語法轉換爲https://github.com/mjackson/citrus/blob/master/lib/citrus/grammars/calc.citrus。在這種情況下,請注意'term'取決於'additive',這又取決於'term'。我認爲這是可以的,因爲在這兩種情況下,我們都指定它前面必須有一個特定的符號(例如「OR」或「AND」)。 – aardvarkk 2014-09-19 21:03:08

+0

我upvoted @MarkThomas,但因爲和表達式消耗「AND」我不認爲這產生了SO。 – 1010 2014-09-22 15:39:57

回答

1

由於gtand_expr - > not_expr和not_expr - > gtand_expr,可能會導致循環。

我認爲你可以

not_expr -> "NOT" not_expr | gtnot_expr 

更換not_expr的規則,你應該使用正則表達式運算符嘗試簡單的規則:

expr -> orexpr 
orexpr -> andexpr ("OR" andexpr)* 
andexpr -> notexpr ("AND" notexpr)* 
notexpr -> "NOT"? atomicexpr 
atomicexpr -> id | "(" expr ")" 
+0

使用「NOT」*如果您想允許連續超過一個的表達式不是。 – 1010 2014-09-22 16:24:30