Вопрос

Я пытаюсь повторить структуру простого оператора 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 операторы).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top