1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
%%
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 }
|
{ [] }
|