我一直在努力通過「現代編譯器在ML中的實現」,我將SML轉換爲OCaml。本書定義了一種名爲Tiger的語言,該語言有一個let ... in ... end
語法用於爲給定表達式聲明範圍內的類型,變量和函數。此外,相同類型的相鄰聲明應該組合在一起以允許相互遞歸。移位/減少與嵌套列表的衝突
我試圖代表這是巨石與下面的文法片段:
%right FUNCTION TYPE
.
.
.
decs: l = list(dec) { l }
dec:
| l = nonempty_list(tydec) { A.TypeDec l }
| v = vardec { v }
| l = nonempty_list(fundec) { A.FunctionDec l }
tydec:
| TYPE; name = ID; EQUAL; ty = ty {
A.{
type_name = Symbol.symbol name;
type_ty = ty;
type_pos = Position.make $startpos $endpos
}
}
有了這個,我得到一個轉變/減少衝突,但巨石解決它,我想的方式。我想nonempty_list(typec)
是貪婪的,所以相鄰的TYPE
聲明被分組在一起。即,與巨石解決衝突產生我AST看起來像:
(LetExp
(decs
((TypeDec
(((type_name (my_type)) (type_ty (NameTy (int))))
((type_name (my_type2)) (type_ty (NameTy (string))))
))))
(body (SeqExp())))
我想擺脫的警告,但我想不出來解決衝突的方式巨石一樣。我試過使用%inline tydec
,這確實會使警告消失,但TYPE
的移位並未如我所料。相反,優選名單中decs
,產生一個看起來像這樣的AST:
(LetExp
(decs
((TypeDec
(((type_name (my_type)) (type_ty (NameTy (int))))))
(TypeDec
(((type_name (my_type2)) (type_ty (NameTy (string)))
)))))
(body (SeqExp())))
我也試着明確設置優先級,但巨石警告我說,這是一個無用的聲明。
我確定我在這裏錯過了一些基本的東西。提供產生列表的產品,我如何使內部列表變得貪婪?
感謝您花時間寫出答案。不幸的是,該語言已經被指定。儘管我可以改變它,但我無法解析與本書相關的一組測試文件。 你說得對,使用分隔符會比使用分隔符容易得多。儘管如此,我希望'tydec'列表可以與一個'A.TypeDec'關聯。生成單獨的'A.TypeDec'實例會大大增加語義分析的複雜度。 – nirvdrum
另一點,如果它在我原來的問題中丟失了。如果我允許警告留下並讓門希爾任意解決衝突,我會得到我期望的行爲。也許這是有缺陷的推理,但我認爲我有一種方法可以指導Menhir在沒有警告的情況下執行相同的解決方案。 – nirvdrum
感謝您的編輯。如果不能使用'%prec'並且'%right'不符合我的要求,我想我沒有太多其他選項。我會看看你提出的更有侵略性的規則。不要聽起來像一個破碎的記錄,但因爲Menhir已經解決了我想要的方式,所以我希望我忽略了一些明顯而簡單的事情。 – nirvdrum