我正在使用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
解析有效的非保留字符串。
现在,我不确定如何表达每行是可选的,但是如果存在的话,仍会获取其值
答案 0 :(得分:0)
首先为您的格式编写上下文无关的语法:
program ::= lines
lines ::= line | line lines
line ::= names | surnames
names ::= NAMES ids
surnames ::= SURNAMES ids
ids ::= id | id ids
id ::= STRING
大写字母名称用于终端时, 小写名称用于非终端。 然后,您可以轻松地使用Alex + Happy来解析您的文本文件。
答案 1 :(得分:0)
您可以执行类似于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)