2010-04-08 46 views
5

我有一些野牛語法:如何讓Bison/YACC在分析整個字符串之前不識別命令?

input: /* empty */ 
     | input command 
; 

command: 
     builtin 
     | external 
; 

builtin: 
     CD { printf("Changing to home directory...\n"); } 
     | CD WORD { printf("Changing to directory %s\n", $2); } 
; 

我不知道我怎麼弄,直到它讀取所有輸入的野牛不接受(YYACCEPT?)的東西作爲command。因此,我可以在下面的所有規則中使用遞歸或其他任何方法來構建事物,這會導致有效的命令或某些不起作用的事情。

我正在用上面的代碼做一個簡單的測試,就是輸入「cd mydir mydir」。野牛解析CDWORD並且「嘿!這是一個命令,把它放在最上面!」。然後找到的下一個標記只是WORD,它沒有規則,然後報告錯誤。

我希望它能夠讀取整行,並且實現CD WORD WORD不是一個規則,然後報告錯誤。我想我錯過了一些明顯的東西,非常感謝任何幫助 - 謝謝!

此外 - 我試過使用input command NEWLINE或類似的東西,但它仍然推動CD WORD頂部作爲一個命令,然後分別解析額外WORD

+0

看起來你的'內建函數應該由換行符(而不是'輸入')終止。正如'CD WORD NEWLINE' – leeeroy 2010-04-08 16:08:59

+0

你的'內建'缺少一個'{',應該''| CD WORD {printf(「更改爲directroy%s \ n」,$ 2); }' – 2010-04-08 16:35:49

+0

哎呀抱歉!這不是我用來測試的代碼... – chucknelson 2010-04-08 16:48:57

回答

2

有時我通過展開我的語法來處理這些情況。

在你的情況下,將標記添加到詞法分析器的換行符和命令分隔符(;)可能是有意義的,因此你可以明確地將它們放入Bison語法中,這樣解析器就可以預期命令的全部輸入行在接受任命之前。

sep: NEWLINE | SEMICOLON 
    ; 

command: CD sep 
    | CD WORD sep 
    ; 

或者,爲參數,像一個真正的外殼任意列表:

args: 
    /* empty */ 
    | args WORD 
    ; 

command: 
     CD args sep 
    ; 
+0

這似乎工作。然而,這是一個無賴,我必須專門提到每個命令的分隔符表達式。在某些時候我可能會改變任意論點......但還沒有!我仍然很好奇,如果有其他方法可以做到這一點... – chucknelson 2010-04-08 16:38:42

+0

糾正:這與2個單詞(CD你好你好),但在這一點上,它彈出的令牌。然後由於某種原因再次啓動。所以「cd hello1 hello2 hello3」會彈出cd,hello1和hello2,但是它會嘗試匹配hello3的單獨規則。我很困惑... – chucknelson 2010-04-08 16:47:58

+0

如果您在上面的第二部分中使用「args」規則,它應該匹配任意數字。 – codenheim 2010-04-08 17:48:43

0

通常情況下,事情沒有按照你描述的方式完成。

有了Bison/Yakk/Lex,人們通常會仔細設計自己的語法來完成他們需要的功能。因爲野牛/雅克/ Lex自然是greedy與他們的正則表達式,這應該幫助你。

那麼,怎麼樣呢,而不是。

由於您一次解析整個,我認爲我們可以利用這個事實來優化和修改語法。

input : /* empty */ 
     | line 


command-break : command-break semi-colon 
       | semi-colon 

line : commands new-line 

commands : commands command-break command 
     | commands command-break command command-break 
     | command 
     | command command-break 

... 

new-line「,分號is defined in yoursource as something like \ n , \ t`。這應該爲您提供您正在查找的命令的UNIX風格語法。各種各樣的事情都是可能的,它有點臃腫,允許多個分號,並沒有考慮到空白,但你應該明白。

Lex和Yakk是一個強大的工具,我發現它們相當令人愉快 - 至少,當你不在最後期限時。

0

不能你只需要改變你的規則匹配的行動將追加到一個動作列表,你想,如果執行整件事情起作用?然後,在處理完整個輸入之後,您可以根據是否出現任何解析錯誤來決定是否要執行該列表中的操作。

1

不是直接調用動作,而是先建立一個抽象語法樹。然後根據結果和你的喜好,你要麼執行它的一部分,要麼什麼都不執行。如果在構建樹的過程中出現解析錯誤,則可能需要使用%destructor指令告訴野牛如何進行清理。

實際上,當你完全控制內容和邏輯,並讓野牛負責解析時,這是一種正確的方式。

+0

感謝您的答案 - 在當前的課程中,我參與了一個項目,我們正在分析語言,構建AST並生成代碼。可悲的是,在我使用Bison和YACC的課程中,我沒有那種經歷。再次感謝,下次我需要做類似的事情時,我可能會考慮這個問題。 – chucknelson 2011-03-22 18:33:47