2017-05-23 4 views
2

練習として、私はEBNF/ABNF文法をMegaparsecで解析しようとしています。私は端末やオプション機能のような簡単なものを持っていますが、私は選択肢に苦しんでいます。EBNFをMegaparsecネストされたsepByで解析する

S ::= 'hello' ['world'] IDENTIFIER LITERAL | 'test'; 

そして、このコード:この文法では

unexpected '|' 
expecting "IDENTIFIER", "LITERAL", ''', '[', or white space 

が、私はそれが発生したときにalternativeTermパーサが生産パーサーに戻っていないと思います。

production :: Parser Production 
production = sepBy1 alternativeTerm (char '|') >>= return . Production 

alternativeTerm :: Parser AlternativeTerm 
alternativeTerm = sepBy1 term space >>= return . AlternativeTerm 

term :: Parser Term 
term = terminal 
    <|> optional 
    <|> identifier 
    <|> literal 

私はこのエラーを取得しますそれを解析することはできず、代わりにエラーがスローされます。

私はこれについて何ができますか? EBNFの私のADTを変更するか、どうやら解析を平らにするべきですか?しかし、もう一度、どうすればいいのですか?

+0

あなたは 'に'(alternativeTermを試してみてください) 'を使用する場合、それはあなたがそれをする方法を動作しますが生産 '?ちょうど推測です。バックトラックが必要なようです。 – Lazersmoke

+0

解析は内部の 'sepBy1'をエスケープしないようです。それは| 「用語」として解釈され、失敗します。代わりに 'sepEndBy1'を使うのはどうですか? –

+0

@Lazersmoke tryはうまくいきません – SuperManitu

答えて

1

これまでのコメントを完全な答えに展開するのが最善でしょう。

あなたの文法は、基本的に、|で区切られた空白で区切られた(そして終了した)用語のリストです。 sepBy1の解は、LITERALの後ろに空白があるために動作しません。sepBy1は、空白に続く別の項があるとみなし、|にtermを適用しようとすると失敗します。

あなたalternativeTermが空白文字(または複数)で終わることが保証されている場合は、次のようにあなたのalternativeTermを書き換える:

alternativeTerm = (term `sepEndBy1` space) >>= return . AlternativeTerm 
+0

ありがとうございます。私はトークナイザを追加する可能性が最も高いので、もうスペースを処理する必要はありません – SuperManitu

関連する問題