2017-02-11 8 views
2

私はParsecで簡単な言語を解析しようとしています。 "x = y"というアサインメントや "prefix test"のような接頭辞があります。ただし、割り当ての解析ルールは貪欲で、「=」がない場合は失敗しません。たとえば、Parsecでプレフィックスを使用しない解析操作

parse tp "" "prefix foo" 

は、解析エラーとなります。対応するコード:

module Test where 
import Text.ParserCombinators.Parsec 
import Text.ParserCombinators.Parsec.Language 
import Text.ParserCombinators.Parsec.Expr 
import qualified Text.ParserCombinators.Parsec.Token as P 

lexer = haskell 
reserved = P.reserved lexer 
reservedOp = P.reservedOp lexer 

data Term = Term String 
    deriving (Show) 

term :: Parser Term 
term = do { x <- many alphaNum 
      ; reservedOp "=" 
      ; y <- many alphaNum 
      ; return (Term (x++y)) 
      } 
    <|> do { reserved "prefix" 
      ; x <- many alphaNum 
      ; return (Term x) 
      } 

tp = do { e<-term; return e } 

何が欠けていますか?私のアプローチは可能ですか、私はParsecを誤解しましたか?

+0

「予約済み」接頭辞「?」の後に 'spaces'を挿入する方法はありますか? – jeiea

+0

私たちは決してこれまでに来たことはない、パーサーは最初のことしか見ない。ルールの順序を変更すると、ステートメントは正しく解析されます。これは、この単純なケースでのみ機能しますが、最初のルールのように多くのルールがあれば、このトリックはもう機能しません。 – hexhex

+0

多くのalphaNumは "接頭辞"を消費しますが、失敗すると動作しません - 入力を消費した後にパーサが失敗すると、別の代替( '<|>'や 'choice'などで与えられます)を試みません。最初のパーサで 'try'が必要です。 (私はあなたが誤ってparsecしていると思う - あなたは自動バックトラックを期待しているが、parsecはこれをしないだけで、他のパーサライブラリがあると思う) – user2407038

答えて

1

コメントでuser2407038が指摘したように、x <- many alphaNumprefixを消費するため、2番目のルールは適用できません。解決策は、tryをブロックの前に置くことです。ストリームの消費された部分を巻き戻します。

関連する問題