анализ, если / else / if операторы
Вопрос
Я пытаюсь повторить структуру простого оператора IF:
if (paren) { block } [else ({ block } | rec if (paren)) ]
Для блока if (paren) я создаю узел ifblock ast. В противном случае он рекурсивно заполняет узел ifelsblock.
Я пробовал довольно много альтернативных конструкций
let parse_if =
suffixparen .>>. suffixblock |>> IfBlock
//>>? attempt (str "else" >>. ifParser) |>> IfElseBlock
//<|> preturn IfBlock
// .>>? attempt (str "else" >>. ifParser) |>> IfElseBlock
// suffixparen .>>. suffixblock |>> IfBlock
// <|> ifParser |>> IfElseBlock
let inlineIf = str_ws "if" >>. parse_if
do ifParserR := inlineIf
Предложения?
Решение
Вы посмотрели на мой анализатор 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
операторы).