aboutsummaryrefslogtreecommitdiff
path: root/lib/parser.mly
blob: 84c1af8f4a44f6ddc376a26dac5e106f0eb92f6c (plain)
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
%{
    module T = Qsp_syntax.T
%}

%parameter<Analyzer: Qsp_syntax.S.Analyzer>
%start <Analyzer.Location.repr>main
%on_error_reduce expression instruction unary_operator assignation_operator

%% 

main: 
    | before_location*
      LOCATION_START
      EOL+
      expressions = line_statement*
      LOCATION_END
    { 
        Analyzer.Location.location $loc expressions
    }

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, statements, loc_s, body = a in 
        let elifs, else_ = match body with 
        | None -> [], []
        | Some (elifs, else_) -> (elifs, else_)
        in
        Analyzer.Instruction.if_
            loc 
            (loc_s, expression, statements) 
            ~elifs
            ~else_
      }
    | a = action_bloc(ACT, empty_body) 
      { let loc, label, statements, _, _ = a in 
        Analyzer.Instruction.act loc ~label statements
      }

(** 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
      { $loc, e, s, $loc(s), b }

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*
    {}