%{ module T = Qsp_syntax.T open StdLabels type action_block = { loc : Qsp_syntax.S.pos ; expression : Qsp_syntax.Report.t list -> Analyzer.Expression.t' * Qsp_syntax.Report.t list ; body : Analyzer.Instruction.t Qsp_syntax.S.repr list ; pos : Qsp_syntax.S.pos ; else_ : ( ( Analyzer.Instruction.clause list * Analyzer.Instruction.t Qsp_syntax.S.repr list ) option ) } module Helper = Qsp_syntax.S.Helper(Analyzer.Expression) module HelperI = Qsp_syntax.S.Helper(Analyzer.Instruction) %} %parameter %start main %on_error_reduce expression instruction unary_operator assignation_operator %% main: | before_location* LOCATION_START EOL+ instructions = line_statement* LOCATION_END { let instructions = List.map instructions ~f:(HelperI.v) in Analyzer.Location.location $loc instructions } before_location: | EOL {} | COMMENT EOL { } (* All these statement should terminate with EOL *) line_statement: | COMMENT EOL+ { Analyzer.Instruction.comment $loc } | COLUMN i=IDENT EOL* { Analyzer.Instruction.location $loc i } | s = terminated(instruction, line_sep) | s = terminated(inline_action, line_sep) { s } | a = action_bloc(IF, elif_else_body) { let {loc; expression; body; pos; else_ } = a in let elifs, else_ = match else_ with | None -> [], [] | Some (elifs, else_) -> (elifs, else_) in Analyzer.Instruction.if_ loc (pos, expression, body) ~elifs ~else_ } | a = action_bloc(ACT, empty_body) { let {loc; expression; body; _} = a in Analyzer.Instruction.act loc ~label:expression body } (** Represent an instruction which can either be on a single line, or created in a block until an END *) %inline action_bloc(TOKEN, BODY): | TOKEN e = expression COLUMN EOL+ s = line_statement* b = BODY END TOKEN? line_sep { let expression = Helper.v e in let else_ = match b with | None -> None | Some (elifs, else_) -> let elifs = begin match elifs with | [] -> [] | _ -> List.map elifs ~f:(fun ((pos:Qsp_syntax.S.pos), e, instructions) -> let e = Helper.v e in (pos, e, instructions) ) end in Some (elifs, else_) in { loc = $loc ; expression ; body = s ; else_ = else_ ; pos = $loc(s) } } empty_body: | { None } elif: | ELIF e = expression COLUMN EOL+ s = line_statement* { $loc, e, s } else_: | ELSE EOL+ expressions = line_statement* { expressions } | { [] } elif_else_body: | elifs = elif* else_ = else_ { Some (elifs, else_) } %inline line_sep: | EOL+ | AMPERSAND+ EOL* {}