在Haskell中进行记录解析

时间:2018-09-04 07:58:12

标签: parsing haskell megaparsec

我正在使用Megaparsec构建解析器,但我不知道哪种方法是解析像这样的结构的最佳方法

names a b c
surnames d e f g

其中namessurnames是关键字,后跟字符串列表,并且这两行都是可选的。这也意味着

names a b c

surnames d e f g

有效。

我可以用类似的东西解析每一行

maybeNames <- optional $ do
    constant "names"
    many identifier

其中identifier解析有效的非保留字符串。

现在,我不确定如何表达每行是可选的,但是如果存在的话,仍会获取其值

2 个答案:

答案 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)