2017-05-10 10 views
2

다음 파서는 모든 입력에 대해 무한 루프를 입력합니다.왜이 파섹 파서는 무한 루프를 입력합니까?

data Ast 
    = Number Int 
    | Identifier String 
    | Operation Ast BinOp Ast 
    deriving (Show, Eq) 

data BinOp = Plus | Minus 
    deriving (Show, Eq, Enum) 

number = Number <$> read <$> many1 digit 

identifier = Identifier <$> many1 letter 

operator = choice $ mkParser <$> [(Plus, '+'), (Minus, '-')] 
    where mkParser (f, c) = f <$ char c 

operation = Operation <$> ast <*> operator <*> ast 

ast :: Parser Ast 
ast = operation <|> number <|> identifier 

문제는 작업 구문 분석기의 어딘가에 있습니다. 대체 파싱과 관련 있다고 생각하지만 이해가되지 않습니다.

문제의 원인을 설명해 주시겠습니까?

감사합니다.

답변

4

문제는 실제로 무한 재귀에 있습니다. ast 파서는 operation 파서를 먼저 호출합니다. 그런 다음 operation 파서가 ast을 다시 호출합니다. 등등. 구문 분석을위한 <*> 연산자도 파서를 실행합니다. <|>과의 차이점에 대한 설명 : <*><|>이 첫 번째 파서를 실행하는지 여부에 관계없이 하나씩 순차적으로 파서를 실행하고 실패 할 경우에만 두 번째 실행합니다.

operation = Operation <$> ast <*> operator <*> ast 
ast  = operation <|> number <|> identifier 

기본적으로 구문 분석기를 다시 사용하더라도 접근 방식이 작동하지 않습니다. 설명과 관련하여이 질문에 대한 답변을 참조하십시오. Megaparsec: Not able to parse arithmetic string