Вы смотрели на мой парсер GLSL (это C-подобный язык)?
http://laurent.le -brun.eu / FSharp / glsl_parse.fs
Из примера кода приведена соответствующая часть для оператора if
:
let statement, stmtRef = createParserForwardedToRef()
let ifStatement =
pipe3 (keyword "if" >>. parenExp) statement (opt (keyword "else" >>. statement))
(fun cond stmt1 stmt2 -> Ast.If(cond, stmt1, stmt2))
stmtRef := choice [
simpleStatement
block
ifStatement
forLoop
//...
]
Я думаю, что ваша проблема в том, что вы используете attempt
вместо opt
. opt
означает, что часть else
является необязательной (если ее там нет, вы получите None
). attempt
совсем другой:
Парсер attempt p
применяет
парсер p
. Если p
не удается после изменения
состояние парсера или со смертельным исходом
ошибка, attempt p
вернется к
исходное состояние синтаксического анализатора и сообщить
нефатальная ошибка.
При сбое синтаксического анализатора в attempt
по-прежнему возникает ошибка, но ввод не используется (полезно в сочетании с операторами <|>
или choice
).