3

Я попытался написать синтаксический анализатор для интерпретатора лямбда-исчисления, который использует грамматики expression closures JavaScript 1.8, что означает function(x) x * x с function(x) { return x * x; }.Как вручную управлять приоритетом специальных выражений в Parsec?

Это мой код парсера.

module Parser where 

import Text.Parsec 
import Text.Parsec.String 
import qualified Text.Parsec.Token as P 
import qualified Text.ParserCombinators.Parsec.Token as T 
import Text.Parsec.Language (emptyDef) 
import Text.Parsec.Expr 
import Control.Applicative ((<*>), (<$>), (*>), (<*), pure, (<$)) 
import Control.Monad 

import Ast 

jsparse :: String -> Either ParseError [Term] 
jsparse = parse prog "" 

-- The scanner. 
lexer = P.makeTokenParser emptyDef { 
    T.commentStart = "/*", 
    T.commentEnd = "*/", 
    T.commentLine = "//", 
    T.nestedComments = True, 
    T.identStart = letter <|> char '_' <|> char '$', 
    T.identLetter  = alphaNum, 
    T.reservedNames = ["function"], 
    T.reservedOpNames = ["="], 
    T.caseSensitive = True 
} 

parens = P.parens lexer 
reserved = P.reserved lexer 
identifier = P.identifier lexer 
whiteSpace = P.whiteSpace lexer 
semi = P.semi lexer 

-- The parser 
prog :: Parser [Term] 
prog = expr `endBy` semi 

term :: Parser Term 
term = termE expr 

termE :: Parser Term -> Parser Term 
termE e = try (parens e) <|> try var <|> func 

expr :: Parser Term 
expr = do whiteSpace 
      e <- term 
      maybeAddSuffix e 
    where addSuffix e0 = do e1 <- term 
          maybeAddSuffix $ TermApp e0 e1 
     maybeAddSuffix e = addSuffix e 
          <|> return e 

var :: Parser Term 
var = do whiteSpace 
     v <- identifier 
     return $ TermVar v 

func :: Parser Term 
func = do whiteSpace 
      reserved "function" 
      v <- parens identifier 
      body <- term 
      return $ TermAbs v body 

Однако есть беда, что function(x) x(x) должен быть проанализирован на (function(x) (x(x))), но мой анализатор получает (function(x) x) (x).

ответ

3

В определении func, body <- term означает, что тело может состоять только из простого термина. Чтобы разрешить все выражения в теле функции, измените ее на body <- expr.

+0

Большое вам спасибо и оно решено. Я изучил эту структуру кода из https://github.com/JakeWheat/intro_to_parsing, но я не понимаю термина «term» и «termE». Зачем мне 'termE e' просто передавать' expr' как аргумент всегда? Как я могу отнести его к BNF? – Ghjhdf

+1

@fiigii Вам не нужен «termE» в таком простом случае, я бы предположил, что учебник использует его более чем для одной цели? Остальное слишком велико, чтобы ответить в комментарии, может быть, вы должны написать новый вопрос? –

+0

Я понял. Спасибо. – Ghjhdf