我試圖爲一個簡單的功能語言,有點像Caml的解析器,但我似乎堅持最簡單的事情。parsec的完整解析器示例?
所以我想知道是否有一些更完整的parsec
解析器的例子,超越了「這是你如何解析2 + 3」。尤其是函數調用等方面。
我讀過「給你寫一個Scheme」,但是Scheme的語法很簡單,並不能真正幫助學習。
我最多的問題是如何利用try
,<|>
和choice
正確,因爲我真的不知道爲什麼秒差距似乎永遠不會使用這個解析器解析a(6)
是一個函數調用:
expr = choice [number, call, ident]
number = liftM Number float <?> "Number"
ident = liftM Identifier identifier <?> "Identifier"
call = do
name <- identifier
args <- parens $ commaSep expr
return $ FuncCall name args
<?> "Function call"
編輯增加了完成一些代碼,雖然這其實不是我問的事情:
AST.hs
module AST where
data AST
= Number Double
| Identifier String
| Operation BinOp AST AST
| FuncCall String [AST]
deriving (Show, Eq)
data BinOp = Plus | Minus | Mul | Div
deriving (Show, Eq, Enum)
Lexer.hs
module Lexer (
identifier, reserved, operator, reservedOp, charLiteral, stringLiteral,
natural, integer, float, naturalOrFloat, decimal, hexadecimal, octal,
symbol, lexeme, whiteSpace, parens, braces, angles, brackets, semi,
comma, colon, dot, semiSep, semiSep1, commaSep, commaSep1
) where
import Text.Parsec
import qualified Text.Parsec.Token as P
import Text.Parsec.Language (haskellStyle)
lexer = P.makeTokenParser haskellStyle
identifier = P.identifier lexer
reserved = P.reserved lexer
operator = P.operator lexer
reservedOp = P.reservedOp lexer
charLiteral = P.charLiteral lexer
stringLiteral = P.stringLiteral lexer
natural = P.natural lexer
integer = P.integer lexer
float = P.float lexer
naturalOrFloat = P.naturalOrFloat lexer
decimal = P.decimal lexer
hexadecimal = P.hexadecimal lexer
octal = P.octal lexer
symbol = P.symbol lexer
lexeme = P.lexeme lexer
whiteSpace = P.whiteSpace lexer
parens = P.parens lexer
braces = P.braces lexer
angles = P.angles lexer
brackets = P.brackets lexer
semi = P.semi lexer
comma = P.comma lexer
colon = P.colon lexer
dot = P.dot lexer
semiSep = P.semiSep lexer
semiSep1 = P.semiSep1 lexer
commaSep = P.commaSep lexer
commaSep1 = P.commaSep1 lexer
Parser.hs
module Parser where
import Control.Monad (liftM)
import Text.Parsec
import Text.Parsec.String (Parser)
import Lexer
import AST
expr = number <|> callOrIdent
number = liftM Number float <?> "Number"
callOrIdent = do
name <- identifier
liftM (FuncCall name) (parens $ commaSep expr) <|> return (Identifier name)
具體的問題應該很容易回答,但我更願意嘗試一個完整的,可編譯的代碼示例來展示您的問題......您能提供一個嗎? – sclv
但是我注意到,你不會在任何地方使用'try'。在你最小的例子中,我不確定它是否重要,但是在任何更大的樣本中它當然會。 – sclv
試圖提供我迄今爲止的整個計劃。 – Lanbo