[英]ambiguous or conflict in LL1 grammar for a shell in C
我正在為執行 shell 實現的項目實現 LL(1) 解析器。 我一直在嘗試解決語法中的沖突:
Parsing mode: LL(1).
Grammar:
1. COMMAND_LINE -> COMPLETE_COMMAND PIPED_CMD
2. PIPED_CMD -> PIPE COMPLETE_COMMAND PIPED_CMD
3. | ε
4. COMPLETE_COMMAND -> CMD_PREFIX CMD CMD_SUFFIX
5. CMD_PREFIX -> REDIRECTION CMD_PREFIX
6. | ε
7. CMD_SUFFIX -> REDIRECTION CMD_SUFFIX
8. | CMD_ARG CMD_SUFFIX
9. | ε
10. REDIRECTION -> REDIRECTION_OP WORD
11. | ε
12. CMD -> WORD
13. CMD_ARG -> WORD CMD_ARG
14. | SINGLE_QUOTE WORD DOUBLE_QUOTE CMD_ARG
15. | DOUBLE_QUOTE WORD DOUBLE_QUOTE CMD_ARG
16. | ε
17. REDIRECTION_OP -> HERE_DOC
18. | APPEND
19. | INFILE
20. | OUTFILE
我使用 syntax-cli 檢查我的語法,而 ll(1) 解析器是一個自制的實現,如果需要我可以鏈接我的解析器實現。 syntax-cli 檢測到的沖突是:
管道 | 單詞 | 單引號 | 雙引號 | HERE_DOC | 附加 | 輸入文件 | 外檔 | $ | |
---|---|---|---|---|---|---|---|---|---|
CMD_SUFFIX | 9 | 7/8 | 7/8 | 7/8 | 7/8 | 7/8 | 7/8 | 7/8 | 9 |
重定向 | 11 | 11 | 11 | 11 | 10/11 | 10/11 | 10/11 | 10/11 | 11 |
命令參數 | 16 | 13/16 | 14/16 | 15/16 | 16 | 16 | 16 | 16 | 16 |
我也試過這個語法:
COMMAND_LINE
: COMPLETE_COMMAND PIPED_CMD
;
PIPED_CMD
: PIPE COMPLETE_COMMAND PIPED_CMD
|
;
COMPLETE_COMMAND
: REDIRECTION CMD REDIRECTION CMD_ARG REDIRECTION
;
REDIRECTION
: REDIRECTION_OP WORD
|
;
CMD
: WORD
;
CMD_ARG
: WORD REDIRECTION CMD_ARG
| SINGLE_QUOTE WORD DOUBLE_QUOTE REDIRECTION CMD_ARG
| DOUBLE_QUOTE WORD DOUBLE_QUOTE REDIRECTION CMD_ARG
| REDIRECTION
;
REDIRECTION_OP
: HERE_DOC
| APPEND
| INFILE
| OUTFILE
;
但是解析器在使用多個重定向時不起作用......
如果沒有代表您的更多規范,則無法確保擁有全部。 但事實上,這個語法是有歧義的。
要構建 LL(1) 分析器,您必須能夠說出,對於分析器堆棧上的符號的任意組合(符號是終端或非終端尚未讀取)和輸入緩沖區中的任何單詞,應該采用什么規則申請。
將自己置於代碼以WORD
開頭的情況(這是輸入緩沖區中的第一件事)
您首先嘗試分析COMMAND_LINE
如果輸入緩沖區以WORD
開頭,那么只有一個規則可以導致COMMAND_LINE
,即規則COMPLETE_COMMAND PIPED_CMD
(無論如何,無論輸入什么,只有這條規則。要么我們可以應用它,要么它是語法錯誤。但現在, 沒有理由引發語法錯誤,此規則與以WORD
開頭的規則兼容)。
所以,現在,在你的堆棧上你有COMPLETE_COMMAND PIPED_CMD
,並且在輸入緩沖區中,仍然是相同的WORD
。
堆棧頂部唯一可能的規則是COMPLETE_COMMAND -> CMD_PREFIX CMD CMD_SUFFIX
所以,現在,在你的堆棧上你有CMD_PREFIX CMD CMD_SUFFIX PIPED_CMD
。
並在輸入緩沖區WORD
中等待
可以從CMD_PREFIX
應用 2 條規則:
CMD_PREFIX -> REDIRECTION CMD_PREFIX
或CMD_PREFIX -> ε
他們都不能以WORD
開頭。 所以要么我們說我們這里有一個空的CMD_PREFIX
(后面是一個以WORD
開頭的CMD
)
或者我們可以將其視為后跟空前綴的REDIRECTION
。 REDIRECTION
可以是REDIRECTION -> ε
所以在這一點上兩者都是可能的。 要么我們有一個CMD_PREFIX(ε)
要么我們有一個CMD_PREFIX(REDIRECTION(ε), ε)
(或者更多的遞歸)。
對於要成為 LL(1) 的文法,我們不應該更深入地決定。 從這一點來看,只要知道下一個詞位是WORD
,我們也應該能夠在其中進行選擇。 我們不是。
(事實上 ,即使使用 LL(1) 以外的其他語法,我們也無法決定)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.