如何在 Parsec 中手动操作特殊表达式的优先级?
How to manually manipulate precedence of special expressions in Parsec?
我尝试为使用 JavaScript 1.8 的 expression closures 语法的 lambda 演算解释器编写解析器,这意味着 function(x) x * x
与 function(x) { return x * x; }
相同。
这是我的解析器代码。
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)
。
在func
的定义中,body <- term
表示正文只能由一个简单的术语组成。要允许函数体中的所有表达式,请将其更改为 body <- expr
.
我尝试为使用 JavaScript 1.8 的 expression closures 语法的 lambda 演算解释器编写解析器,这意味着 function(x) x * x
与 function(x) { return x * x; }
相同。
这是我的解析器代码。
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)
。
在func
的定义中,body <- term
表示正文只能由一个简单的术语组成。要允许函数体中的所有表达式,请将其更改为 body <- expr
.