%% empty: | {} (** The whole block is parametrized over a token named END. In most of the cases this token indicate the end of line, but in the case of recursive inline instruction, this can become an empty marker (because the whole instruction is nested inside a end_line terminated block) *) %public inlined_block(END): | s = terminated(instruction, END) { s } | a = onliner(ACT) END { let loc, label, statements, _, _ = a in let label = Analyzer.Expression.v label in Analyzer.Instruction.act loc ~label statements } (* This case create a conflict in the resolution : the case if a: if b: '' else '' can be interpreted as if a: (if b: '' else '') or if a: (if b: '') else '' *) | a = onliner(IF) else_opt = preceded(ELSE, inlined_block(empty))? END { let loc, expr, statements, loc_s, _body = a in let elifs = [] and else_ = match else_opt with | None -> None | Some instructions -> Some ($loc(else_opt), [ instructions ]) in Analyzer.Instruction.if_ loc (loc_s, Analyzer.Expression.v expr, statements) ~elifs ~else_ } final_inline_instruction: | hd = inline_instruction tl = inlined_block(empty) { tl :: hd } | hd = inline_instruction COMMENT { (Analyzer.Instruction.comment $loc) :: hd } onliner(TOKEN): | TOKEN e = expression COLUMN s = rev (final_inline_instruction) { $loc, e, s, $loc(s), None } (* This is basicaly just a loop to add as many instruction separated by & *) inline_instruction: | hd = inline_instruction tl = instruction AMPERSAND+ { tl :: hd } | { [] }