Разбор записи в Хаскеле - PullRequest
       17

Разбор записи в Хаскеле

0 голосов
/ 04 сентября 2018

Я создаю синтаксический анализатор, используя 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 анализирует допустимую незарезервированную строку.

Теперь я не уверен, как выразить, что каждая строка является необязательной, но все же получить ее значение, если оно присутствует

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Вы можете сделать что-то похожее на то, что появляется в этом руководстве и использовать <|> выбрать необязательные аргументы. Вот суть вещей:

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)
0 голосов
/ 04 сентября 2018

Начните с написания контекстно-свободной грамматики для вашего формата:

program  ::= lines
lines    ::= line | line lines
line     ::= names | surnames
names    ::= NAMES ids
surnames ::= SURNAMES ids
ids      ::= id | id ids
id       ::= STRING

Где имена в верхнем регистре для терминалов, и строчные имена предназначены для нетерминалов. Затем вы можете легко использовать Alex + Happy для анализа вашего текстового файла.

...