#parsing #haskell #eval
#синтаксический анализ #haskell #оценка
Вопрос:
У меня возникла проблема, из-за которой мой анализатор для блоков if (и блоков Do-While, потому что проблема одна и та же) не завершается при разборе строки «fi». If-блок принимает форму:
if P -> p
[] Q -> q
fi
Если я использую Text.Parsec
анализатор строк для синтаксического "fi"
анализа, как я использовал его для синтаксического "if"
анализа, чтобы даже войти в цикл, программа останавливается. Когда я распечатываю то, что должно быть оценено, его даже нет, поэтому программа даже не вводит If-блок, когда он заканчивается "fi"
.
Однако, когда я удаляю синтаксический анализатор, который анализирует "fi"
, происходит то, что программа может запускаться, и оценка If-блока выполняется так, как ожидалось, но я должен завершить блок тем же числом "fi"
(или любой строкой), что и выражения внутри самого блока. Если я не завершу блок с тем же числом "fi"
‘s, произойдет любое утверждение после того, как блок будет оцениваться бесконечно. Например, блок, который добавляет единицу к текущему итогу, если переменная четная, будет выглядеть так:
if ((x mod 2) = 0)-> r := r 1
[] ((x mod 2) = 1)-> r := r 0
fi
fi
И если бы был один "fi"
, и я напечатал значение r после блока, оно печатало бы r бесконечно
if ((x mod 2) = 0)-> r := r 1
[] ((x mod 2) = 1)-> r := r 0
fi
print(r)
./Main prog
1
1
1
1
1
...
Проблема, вероятно, в неправильном использовании spaces
функции, но, похоже, я не могу правильно выполнить синтаксический анализ, даже когда я удаляю все экземпляры пробелов, чтобы все было в одной строке, объединенной вместе. Даже когда я это сделаю, он не будет принят "fi"
в коде синтаксического анализатора, но он примет его, если это то же число, что и выражения при его удалении.
parseIf :: Parser HStatement
parseIf = do
try (string "if") <|> try (string "[]")
spaces
string "("
cond <- parseVals
string ")->"
spaces
expr <- many1 $ parseStatements
spaces
return $ If (cond, expr)
parseSelection :: Parser HStatement
parseSelection = do
selection <- many1 parseIf
spaces
--try (string "fi")
return $ Selection selection
parseStatements :: Parser HStatement
parseStatements = try (parseDo) <* spaces <|> try (parseSelection) <|> try (parsePrint) <|> try (parseEvalHVal)
Комментарии:
1. Это не рабочий пример, поэтому я не могу его протестировать, но мое первое предположение заключается в том, что что-то не работает с пробелами. В частности, когда вы выполняете синтаксический
many $ try parseStatements
анализ, не похоже, что вы заботитесь о пробелах между несколькими операторами.2. Как говорит @DDub,
parseStatements
я бы проанализировал что-то вродеx := x 1
, но вы хотите проанализировать<many space>x := x 1
. Я думаю, что что-то в линииmany $ try (optional spaces >> parseStatements)
shoud работает.3. Правильно, поэтому я изменил
many $ try parseStatements
many $ (spaces *> parseStatements <* spaces)
и добавилspaces
после каждой строки в каждом анализаторе, например, я добавил его передx
inparseArith
, и поведение по-прежнему сохраняется4. Поведение странное, потому что я пытался
many $ try (optional spaces >> parseStatements)
, и поведение осталось прежним, но дело в том, что я могу выполнять выражения, подобныеx := x 1
in sequence, без цикла, без проблем5. @JiangShi ты можешь попробовать без отступов внутри
Do-Od
? просто чтобы проверить, не в этом ли проблема. Другое делоspaces
, что не включеноText.Parsec
, как это определяется?