簡體   English   中英

Bison Shift / Reduce沖突實現簡單語法

[英]Bison Shift/Reduce conflict for simple grammar

我正在為我設計的語言構建一個解析器,其中類型名稱以大寫字母開頭,變量名稱以小寫字母開頭,以便詞法分析器可以區分兩者並提供不同的標記。 同樣,字符串“ this”由詞法分析器(它是一種OOP語言)識別,並作為單獨的令牌傳遞。 最后,只能在“ this”對象上訪問數據成員,因此我這樣構建了語法:

%token TYPENAME
%token VARNAME
%token THIS

%%

start:
    Expression
    ;

Expression:
    THIS
    | THIS '.' VARNAME
    | Expression '.' TYPENAME
    ;
%%

Expression的第一個規則允許用戶將“ this”作為值傳遞(例如,從方法返回它或傳遞給方法調用)。 第二個是用於訪問“ this”上的數據。 第三條規則用於調用方法,但是我刪除了方括號和參數,因為它們與問題無關。 最初的語法顯然要大得多,但是這是產生相同錯誤(最小的Shift / Reduce沖突)的最小部分-我將其隔離到自己的解析器文件中並進行了驗證,因此該錯誤與任何錯誤無關其他符號。

據我所知,這里給出的語法是明確的,因此不會產生任何錯誤。 如果刪除這三個規則中的任何一個或將第二個規則更改為

Expression '.' VARNAME

沒有沖突。 無論如何,我可能都需要有人清楚地說明發生這種沖突的原因以及如何解決它。

問題在於語法只能向前看。 因此,當您看到一個THIS一個. ,您處於第2行( Expression: THIS '.' VARNAME )還是第3行( Expression: Expression '.' TYPENAME ,根據第1行進行了歸約)。

語法可以減少這種情況THIS. Expression. 然后尋找TYPENAME或將其移至THIS. 並尋找一個VARNAME ,但是它必須決定什么時候到達.

我嘗試避免y.output,但有時確實有幫助。 我看了看它產生的文件。

state 1

    2 Expression: THIS.  [$end, '.']
    3           | THIS . '.' VARNAME

    '.'  shift, and go to state 4

    '.'       [reduce using rule 2 (Expression)]
    $default  reduce using rule 2 (Expression)

基本上是說看到“。” 並可以減少或移動。 減少有時使我煩惱,因為它們很難罰款。 移位是規則3,很明顯(但輸出未提及規則#)。 減少的地方是“。” 在這種情況下是線

| Expression '.' TYPENAME

當它關系到表達它着眼於下一個字母(的“”),去的現在看到。 THIS | 因此,當到達該語句的末尾時,它期望為“。” 當它離開或錯誤時。 但是,它看到此“。” 而在此和“。”之間 (因此,out文件中的點)會減少規則,因此會出現路徑沖突。 我相信您可以使用%glr-parser來嘗試兩者,但是沖突越多,您越有可能獲得意外的輸出或歧義錯誤。 我過去有歧義錯誤。 他們很煩人,尤其是如果您不記得是什么規則導致或影響了他們。 建議避免沖突。

在嘗試使用野牛之前,我強烈推薦這本書

我想不出一個“偉大的”解決方案,但這沒有沖突

start:
    ExpressionLoop
    ;

ExpressionLoop:
      Expression
    | ExpressionLoop ';' Expression
    ;
Expression:
      rval 
    | rval '.' TYPENAME
    | THIS //trick is moving this AWAY so it doesnt reduce
rval:

    THIS '.' VARNAME

或者,您可以通過向規則中添加更多內容來使其稍后減少,從而使其不會立即減少,或者在之后或之前添加令牌以明確采用哪個路徑或失敗(請記住,在減少任何路徑之前,它必須知道)

start:
    ExpressionLoop
    ;

ExpressionLoop:
      Expression
    | ExpressionLoop ';' Expression
    ;
Expression:
      rval 
    | rval '.' TYPENAME
rval:
      THIS '@'
    | THIS '.' VARNAME
%%

-edit-請注意,如果我想執行func paramtype varname無法進行,因為根據詞法分析器func的類型是Var(也是A-Za-z09_)。 param和varname都是var的,所以這會導致我減少/減少沖突。 您不能將它們寫成它們的樣子,只能寫成它們的外觀。 因此,在編寫時請記住這一點。 您必須編寫一個令牌來區分兩者,或將其寫為兩者之一,但在代碼中(規則右側{}中的部分)編寫其他邏輯,以檢查它是否為funcname或並處理這兩種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM