Haskell Megaparsec - Reserved word parsed as identifier
up vote
2
down vote
favorite
I'm trying to parse a simple language with lamdba expressions. But runParser expr "lamdbda(x) (return x)
returns Right (Var "lamdba")
instead of Right (Lambda ["x"] (Return (Var "x")))
My guess is, that I have to add a try
somewhere, but I can't figure out where. lambdaExpr
parses lamdbas correctly.
Ast.hs
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
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
haskell megaparsec
add a comment |
up vote
2
down vote
favorite
I'm trying to parse a simple language with lamdba expressions. But runParser expr "lamdbda(x) (return x)
returns Right (Var "lamdba")
instead of Right (Lambda ["x"] (Return (Var "x")))
My guess is, that I have to add a try
somewhere, but I can't figure out where. lambdaExpr
parses lamdbas correctly.
Ast.hs
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
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
haskell megaparsec
1
Did you misspell "lambda"?
– danidiaz
Nov 10 at 13:12
1
Have you tried using thedbg
function to see why it doesn't match? stackage.org/haddock/lts-12.17/megaparsec-6.5.0/… Try addinglambdaExpr = dbg "lambdaExpr" $ do
.
– Icid
Nov 10 at 13:54
I did indeed misspell "lmbda", the debug function helped
– Philipp Siegmantel
Nov 10 at 14:05
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I'm trying to parse a simple language with lamdba expressions. But runParser expr "lamdbda(x) (return x)
returns Right (Var "lamdba")
instead of Right (Lambda ["x"] (Return (Var "x")))
My guess is, that I have to add a try
somewhere, but I can't figure out where. lambdaExpr
parses lamdbas correctly.
Ast.hs
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
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
haskell megaparsec
I'm trying to parse a simple language with lamdba expressions. But runParser expr "lamdbda(x) (return x)
returns Right (Var "lamdba")
instead of Right (Lambda ["x"] (Return (Var "x")))
My guess is, that I have to add a try
somewhere, but I can't figure out where. lambdaExpr
parses lamdbas correctly.
Ast.hs
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
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
haskell megaparsec
haskell megaparsec
asked Nov 10 at 12:47
Philipp Siegmantel
53236
53236
1
Did you misspell "lambda"?
– danidiaz
Nov 10 at 13:12
1
Have you tried using thedbg
function to see why it doesn't match? stackage.org/haddock/lts-12.17/megaparsec-6.5.0/… Try addinglambdaExpr = dbg "lambdaExpr" $ do
.
– Icid
Nov 10 at 13:54
I did indeed misspell "lmbda", the debug function helped
– Philipp Siegmantel
Nov 10 at 14:05
add a comment |
1
Did you misspell "lambda"?
– danidiaz
Nov 10 at 13:12
1
Have you tried using thedbg
function to see why it doesn't match? stackage.org/haddock/lts-12.17/megaparsec-6.5.0/… Try addinglambdaExpr = dbg "lambdaExpr" $ do
.
– Icid
Nov 10 at 13:54
I did indeed misspell "lmbda", the debug function helped
– Philipp Siegmantel
Nov 10 at 14:05
1
1
Did you misspell "lambda"?
– danidiaz
Nov 10 at 13:12
Did you misspell "lambda"?
– danidiaz
Nov 10 at 13:12
1
1
Have you tried using the
dbg
function to see why it doesn't match? stackage.org/haddock/lts-12.17/megaparsec-6.5.0/… Try adding lambdaExpr = dbg "lambdaExpr" $ do
.– Icid
Nov 10 at 13:54
Have you tried using the
dbg
function to see why it doesn't match? stackage.org/haddock/lts-12.17/megaparsec-6.5.0/… Try adding lambdaExpr = dbg "lambdaExpr" $ do
.– Icid
Nov 10 at 13:54
I did indeed misspell "lmbda", the debug function helped
– Philipp Siegmantel
Nov 10 at 14:05
I did indeed misspell "lmbda", the debug function helped
– Philipp Siegmantel
Nov 10 at 14:05
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
I misspelled "lambda", closing this question.
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
I misspelled "lambda", closing this question.
add a comment |
up vote
0
down vote
I misspelled "lambda", closing this question.
add a comment |
up vote
0
down vote
up vote
0
down vote
I misspelled "lambda", closing this question.
I misspelled "lambda", closing this question.
answered Nov 10 at 14:06
Philipp Siegmantel
53236
53236
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53239098%2fhaskell-megaparsec-reserved-word-parsed-as-identifier%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Did you misspell "lambda"?
– danidiaz
Nov 10 at 13:12
1
Have you tried using the
dbg
function to see why it doesn't match? stackage.org/haddock/lts-12.17/megaparsec-6.5.0/… Try addinglambdaExpr = dbg "lambdaExpr" $ do
.– Icid
Nov 10 at 13:54
I did indeed misspell "lmbda", the debug function helped
– Philipp Siegmantel
Nov 10 at 14:05