yaccで死亡
正確には ply の yacc ですけどももも
…いやぁ全然概念が判らなくて大苦戦ですわ(苦笑
学習がてら、以下に合致するパーサーを作ろうかと思ったわけです。ドット区切りで要素3つまで。
- a
- b.a
- c.b.a
- 正規表現的にはこんな感じ → ((\w+\.)?\w\.)?\w+
イメージ的には foo.ir9.jp / ir9.jp / jp を解析するパーサーを作りたい的な。 で、こんな感じなの書きました
## lex tokens = ( "NAME", "PERIOD", ) t_NAME = r"\w+" t_PERIOD = r"\." ## yacc def p_host(p): """ host : NAME PERIOD NAME PERIOD NAME | NAME PERIOD NAME | NAME """ p[0] = ''.join(p[1:]) yacc.yacc() print(yacc.parse("c.b.a")) # c.b.a print(yacc.parse("b.a")) # b.a print(yacc.parse("a")) # a
動きました。良かったよかった!
…ではあるんですが、各NAMEの要素に名前というか意味合いを付けたほうがよいのかなと。今後各要素に適用できる文字の定義を変えるかもしれないし! …ってことで、次のように改修してみました。 "[ [sub . ] domain .] cont" というイメージ。
## lex tokens = ( "NAME", "PERIOD", ) t_NAME = r"\w+" t_PERIOD = r"\." ## yacc def p_host(p): """ host : domain PERIOD cunt | NAME """ p[0] = ''.join(p[1:]) def p_cunt(p) : """ cunt : NAME """ p[0] = p[1] def p_domain(p) : """ domain : sub PERIOD NAME | NAME """ p[0] = ''.join(p[1:]) def p_sub(p) : """ sub : NAME """ p[0] = p[1] yacc.yacc() print(yacc.parse("c.b.a")) # a // Syntax error at line 1, token=PERIOD print(yacc.parse("b.a")) # b.a print(yacc.parse("a")) # a # WARNING: 1 reduce/reduce conflict # WARNING: reduce/reduce conflict in state 3 resolved using rule (domain -> NAME) # WARNING: rejected rule (sub -> NAME) in state 3 # WARNING: Rule (sub -> NAME) is never reduced
ダメだってさ!
…って所でめっちゃ詰まってます。 おそらく「スタックに NAME 積んだ後 PERIOD 来ると、domain なんだか sub なんだか判断つかねぇんだよ!2回死ね!それと便座カバー」って事だとは思っているんですが、いかんせん yacc の挙動・動作・考え方が解っていないため全く確信が持てず。 ついでに解決方法も良くわからん… そもそもコレ「右結合」なんじゃないのと思いつつ、それがどう記述に影響してくるのか・考え方にどう影響してくるのかとかもよくわからず… ぐぬぬ……
構文解析難しいわ…