首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell Megaparsec被解析为标识符的保留字

Haskell Megaparsec被解析为标识符的保留字
EN

Stack Overflow用户
提问于 2018-11-10 12:47:10
回答 1查看 627关注 0票数 4

我试图用lamdba表达式解析一种简单的语言。但是runParser expr "lamdbda(x) (return x)返回Right (Var "lamdba")而不是Right (Lambda ["x"] (Return (Var "x")))

我的猜测是,我必须在某个地方添加一个try,但我不知道在哪里。lambdaExpr正确地解析lamdbas。

Ast.hs

代码语言:javascript
复制
data Expr = Const Integer
          | BinOp Op Expr Expr
          | Neg Expr
          | If Expr Expr Expr
          | Var String
          | Lambda [String] Stmt
  deriving (Show, Eq)

data Op = Multiply
        | Divide
        | Add
        | Subtract
  deriving (Show, Eq)

data Stmt = Decl String Expr
          | Seq [Stmt]
          | Print Expr
          | Return Expr
  deriving (Show, Eq)

Parser.hs

代码语言:javascript
复制
module Parser where

import Ast

import Control.Monad
import Data.Void
import Control.Monad.Combinators.Expr
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L

type Parser = Parsec Void String

sc :: Parser ()
sc = L.space space1 lineCmnt blockCmnt
  where lineCmnt = L.skipLineComment "--"
        blockCmnt = L.skipBlockComment "{-" "-}"

lexeme :: Parser a -> Parser a
lexeme = L.lexeme sc

symbol :: String -> Parser String
symbol = L.symbol sc

parens :: Parser a -> Parser a
parens = between (symbol "(") (symbol ")")


integer :: Parser Integer
integer = lexeme L.decimal

rword :: String -> Parser ()
rword w = (lexeme . try) (string w *> notFollowedBy alphaNumChar)

rws :: [String] -- list of reserved words
rws = ["if", "then", "else", "let", "print", "lambda", "return"]

identifier :: Parser String
identifier = (lexeme . try) (p >>= check)
  where
    p       = (:) <$> letterChar <*> many alphaNumChar
    check x = if x `elem` rws
              then fail $ "keyword " ++ show x ++ " cannot be an identifier"
              else return x

ifExpr :: Parser Expr
ifExpr = do rword "if"
            cond <- expr
            rword "then"
            thn <- expr
            rword "else"
            els <- expr
            return $ If cond thn els

lambdaExpr :: Parser Expr
lambdaExpr = do rword "lambda"
                args <- parens $ sepBy identifier (char ',')
                s <- stmt
                return $ Lambda args s

expr :: Parser Expr
expr = makeExprParser term operators

term :: Parser Expr
term = parens expr
  <|> lambdaExpr
  <|> Const <$> integer
  <|> Var <$> identifier
  <|> ifExpr

operators :: [[Operator Parser Expr]]
operators =
  [ [Prefix (Neg <$ symbol "-") ]
  , [ InfixL (BinOp Multiply <$ symbol "*")
    , InfixL (BinOp Divide   <$ symbol "/") ]
  , [ InfixL (BinOp Add      <$ symbol "+")
    , InfixL (BinOp Subtract <$ symbol "-") ]
  ]

declStmt :: Parser Stmt
declStmt = do rword "let"
              name <- identifier
              void $ symbol "="
              e <- expr
              return $ Decl name e

printStmt :: Parser Stmt
printStmt = do rword "print"
               e <- expr
               return $ Print e

returnStmt :: Parser Stmt
returnStmt = do rword "return"
                e <- expr
                return $ Return e

stmt :: Parser Stmt
stmt = f <$> sepBy1 stmt' (symbol ";")
  where
    -- if there's only one stmt return it without using ‘Seq’
    f l = if length l == 1 then head l else Seq l

stmt' :: Parser Stmt
stmt' = declStmt
        <|> printStmt
        <|> returnStmt

runParser :: Parser a -> String -> Either (ParseError (Token String) Void) a
runParser p input = Text.Megaparsec.runParser p "" input
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-10 14:06:27

我拼错了"lambda“结束了这个问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53239098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档