我正在使用Megaparsec构建解析器,我不知道解析结构的最佳方法是哪种
names a b c
surnames d e f g
其中names
和surnames
是关键字后跟一个字符串列表,两行中的每一行都是可选的。这也意味着
names a b c
和
surnames d e f g
是有效的。
我可以用类似的东西解析每一行
maybeNames <- optional $ do
constant "names"
many identifier
其中identifier
解析有效的非保留字符串。
现在,我不确定如何表达每一行是可选的,但如果它存在,仍然检索它的值
首先为您的格式编写上下文无关语法:
program ::= lines
lines ::= line | line lines
line ::= names | surnames
names ::= NAMES ids
surnames ::= SURNAMES ids
ids ::= id | id ids
id ::= STRING
大写名称用于终端,小写名称用于非终端。然后,您可以轻松使用Alex + Happy来解析文本文件。
您可以执行与this guide中显示的操作类似的操作,并使用<|>
选择可选参数。以下是事物的本质:
whileParser :: Parser Stmt
whileParser = between sc eof stmt
stmt :: Parser Stmt
stmt = f <$> sepBy1 stmt' semi
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' = ifStmt
<|> whileStmt
<|> skipStmt
<|> assignStmt
<|> parens stmt
ifStmt :: Parser Stmt
ifStmt = do
rword "if"
cond <- bExpr
rword "then"
stmt1 <- stmt
rword "else"
stmt2 <- stmt
return (If cond stmt1 stmt2)
whileStmt :: Parser Stmt
whileStmt = do
rword "while"
cond <- bExpr
rword "do"
stmt1 <- stmt
return (While cond stmt1)