3

我試着爲lambda-calculus解釋器編寫解析器,該解釋器使用expression closures JavaScript 1.8的語法,這意味着function(x) x * xfunction(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 2015-03-03 08:24:11

+1

@fiigii在這種簡單的情況下,你並不需要'termE',我會假設該教程將它用於多個目的?其餘的內容太大,無法在評論中回答,也許你應該發佈一個新問題? – 2015-03-03 08:42:20

+0

我明白了。謝謝。 – Ghjhdf 2015-03-03 08:46:29