YACC for ansi C 的文法在很多地方都可以找到了。為什麼沒有Python的?如何把Python原始碼中的grammar編譯成yacc的?
回複內容:
理論上是可以的,關鍵點在於您要在Lexer和Parser之間要多加一層,用於分析哪些地方是進入縮排,哪些地方是退出縮排。然後匹配到縮排的時候插入INDENT和DEDENT這樣的Token。
至於分析的方法,您可以先建一個Stack來存放每一層縮排塊的Token,
然後根據Lexer送來的Token中的行號、列號等資訊來和Stack棧頂的資料進行對比,
判斷下來是該進入縮排的就push一個INDENT,並這個INDENT插入到輸出的Token流中。
發現是Stack中舊的Token匹配的,就把之前的縮排塊pop出來,並在輸出的Token流中插入DEDENT。
然後在Paser層面處理語句塊的時候可以這樣處理(我唯寫大概意思的偽碼,具體您自己看著辦)
block ::= INDENT NLS statements NLS DEDENT
if ::= IF LPAREN expression RPAREN COLON block
1:python這種靠縮排的語言的文法其實是上下文有關的,EBNF是表達不出來的,我不知道yacc是不是有什麼喪心病狂的擴充來給你做這個。
2:每一行前面的tab的數量你不要看成一堆tab,要把他的數量本身看成一個整體,也就是說再作文法分析的時候其實是:
[0]def fuck[1]if true:[2]fuck[1]else:[2]shit[0]def shit..
主要是縮排文法的問題吧,只要先在詞法上把python的縮排改成類似大括弧分界的文法即可,壓力在lex這邊
cpython源碼的token分析是用C手擼的,超長,可以看看源碼補充一下 @vczh ,因為是上下文有關的,所以Yacc是不行的,不過我通過 peg, ometa 解決什麼問題,ometa-js怎麼入門/正確理解和認知? 這個問題知道 PEG 適合進行。
pyPEG
這個項目的首頁,底下就有對縮排的分析,可以參考一下。
我用C語言實現過一個簡化的python解譯器,用yacc來分析python的思路如下:
1. 在來源程式中插入兩個虛擬TOKEN:TOKEN_BEGIN和TOKEN_END
TOKEN_BEGIN標誌文法塊的開始,TOKEN_END標誌文法塊的結束。看一個例子:
while i < 100: print i i += 1
還不如直接看python源碼裡的interpreter好了。COOL都日出來了,python算個DIAO啊,文法拿去,玩吧。寫完了我們膜拜一下。
https://github.com/python-git/python/blob/master/Grammar/Grammar