簡體   English   中英

移位/減少模棱兩可的語法沖突

[英]Shift/reduce conflict with ambiguous grammar

由於yacc報告了6個shift / reduce沖突,我一直被一些模棱兩可的語法所困擾。 我查看了y.output文件,並試圖了解如何查看狀態並找出解決歧義語法但無濟於事的方法。 我被合理地固定在應該如何解決這些問題上。 我查看了很多關於堆棧溢出的問題,以了解其他人的解釋是否可以幫助我解決我的問題,但這也沒有太大幫助。 作為記錄, 我不能使用任何優先級定義指令(例如%left來解決解析沖突。

有人可以通過指導我如何更改語法來解決班次/減少沖突的問題來幫助我嗎? 也許通過嘗試解決其中一個問題並向我展示其背后的思維過程? 我知道語法很長很重,為此我深表歉意。 如果有人願意為此騰出時間,那將不勝感激,但我意識到我可能無法擁有。

無論如何,這是我所關注的語法(它是MiniJava語法的略微擴展):

Grammar
0 $accept: program $end

1 program: main_class class_decl_list

2 main_class: CLASS ID '{' PUBLIC STATIC VOID MAIN '(' STRING '[' ']' ID ')' '{' statement '}' '}'

3 class_decl_list: class_decl_list class_decl
4                | %empty

5 class_decl: CLASS ID '{' var_decl_list method_decl_list '}'
6           | CLASS ID EXTENDS ID '{' var_decl_list method_decl_list '}'

7 var_decl_list: var_decl_list var_decl
8              | %empty

9 method_decl_list: method_decl_list method_decl
10                 | %empty

11 var_decl: type ID ';'

12 method_decl: PUBLIC type ID '(' formal_list ')' '{' var_decl_list statement_list RETURN exp ';' '}'

13 formal_list: type ID formal_rest_list
14            | %empty

15 formal_rest_list: formal_rest_list formal_rest
16                 | %empty

17 formal_rest: ',' type ID

18 type: INT
19     | BOOLEAN
20     | ID
21     | type '[' ']'

22 statement: '{' statement_list '}'
23          | IF '(' exp ')' statement ELSE statement
24          | WHILE '(' exp ')' statement
25          | SOUT '(' exp ')' ';'
26          | SOUT '(' STRING_LITERAL ')' ';'
27          | ID '=' exp ';'
28          | ID index '=' exp ';'
29 statement_list: statement_list statement
30               | %empty

31 index: '[' exp ']'
32      | index '[' exp ']'

33 exp: exp OP exp
34    | '!' exp
35    | '+' exp
36    | '-' exp
37    | '(' exp ')'
38    | ID index
39    | ID '.' LENGTH
40    | ID index '.' LENGTH
41    | INTEGER_LITERAL
42    | TRUE
43    | FALSE
44    | object
45    | object '.' ID '(' exp_list ')'

46 object: ID
47       | THIS
48       | NEW ID '(' ')'
49       | NEW type index

50 exp_list: exp exp_rest_list
51         | %empty

52 exp_rest_list: exp_rest_list exp_rest
53              | %empty
54 exp_rest: ',' exp

這是來自y.output的具有移位/減少沖突的相關狀態。

State 58
7 var_decl_list: var_decl_list . var_decl
12 method_decl: PUBLIC type ID '(' formal_list ')' '{' var_decl_list . statement_list RETURN exp ';' '}'

INT      shift, and go to state 20
BOOLEAN  shift, and go to state 21
ID       shift, and go to state 22

ID        [reduce using rule 30 (statement_list)]
$default  reduce using rule 30 (statement_list)

var_decl        go to state 24
type            go to state 25
statement_list  go to state 69


State 76
38 exp: ID . index
39    | ID . '.' LENGTH
40    | ID . index '.' LENGTH
46 object: ID .

'['  shift, and go to state 64
'.'  shift, and go to state 97

'.'       [reduce using rule 46 (object)]
$default  reduce using rule 46 (object)

index  go to state 98


State 100
33 exp: exp . OP exp
34    | '!' exp .

OP  shift, and go to state 103

OP        [reduce using rule 34 (exp)]
$default  reduce using rule 34 (exp)


State 101
33 exp: exp . OP exp
35    | '+' exp .

OP  shift, and go to state 103

OP        [reduce using rule 35 (exp)]
$default  reduce using rule 35 (exp)


State 102
33 exp: exp . OP exp
36    | '-' exp .

OP  shift, and go to state 103

OP        [reduce using rule 36 (exp)]
$default  reduce using rule 36 (exp)


State 120
33 exp: exp . OP exp
33    | exp OP exp .

OP  shift, and go to state 103

OP        [reduce using rule 33 (exp)]
$default  reduce using rule 33 (exp)

我們終於得到它了。 對於這種語法的長度以及移位/減少沖突的次數,我再次表示歉意。 我似乎無法理解如何通過更改相關語法來解決這些問題。 我們將不勝感激任何幫助,盡管如果沒有人有時間瀏覽如此龐大的職位,我將理解。 如果有人需要更多信息,請隨時詢問。

基本問題是,在解析method_decl主體時,它無法確定var_decl_list結束位置和statement_list開始位置。 這是因為當前瞻是ID ,它不知道那是另一個var_decl的開始還是第一條statement的開始,並且它需要減少一個空語句才能開始對statement_list

您可以通過多種方式處理此問題:

  • 讓詞法分析器為類型ID和其他ID返回不同的令牌-這樣,差異將告訴解析器下一個。

  • 語句列表的開頭不需要空語句。 將語法更改為:

     statement_list: statement | statement_list statement ; opt_statement_list: statement_list | %empty ; 

    並在method_decl規則中使用opt_statement_list 可以解決在開始分析語句之前必須減少空的statement_list的問題。 當您用多個變體替換規則時,此過程稱為“解因”語法。 它使語法更加復雜,在這種情況下,它不能解決問題,而只是解決問題。 您將在以下statement: ID . index看到轉移/減少沖突statement: ID . index statement: ID . indextype: ID [前瞻性type: ID 這個問題也可以通過分解來解決,但難度更大。


因此,這提出了通過分解來解決移位減少沖突的一般思想。 基本思想是擺脫導致班次減少沖突減少的規則,而將其替換為上下文中更受限制的規則,因此不要觸發沖突。 上面的示例很容易通過“用1個或多個遞歸重復和一個可選規則替換0個或多個遞歸重復”來解決。 如果以下情況意味着您可以輕松地確定何時0例應合法(在這種情況下僅當下一個標記為} ,這對於重復的epsilon規則上的shift-reduce沖突效果很好。

第二個沖突更加嚴峻。 這里的沖突在於減少type: ID當超前為[時的type: ID 因此,我們需要重復類型規則,直到沒有必要為止。 就像是:

type: simpleType | arrayType ;
simpleType: INT | BOOLEAN | ID ;
arrayType: INT '[' ']' | BOOLEAN '[' ']' | ID '[' ']'
         | arrayType '[' ']' ;

'[' ']'后綴的0個或多個重復”替換為“ 1個或多個”,並出於類似的原因工作(將減少量推遲到看到'[' ']'后再使用,而不是之前要求。)關鍵是當lookahead為'['時,永遠不需要減少simpleType: ID規則,因為它僅在其他上下文中有效。

暫無
暫無

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

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