aboutsummaryrefslogtreecommitdiffstats
path: root/lib/parser.mly
blob: c85eccc2dab88705aad58f0401a501ce99c0b311 (plain) (blame)
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
%{
open Ast
%}

%token <Z.t> INT
%token <Z.t * Z.t> RAT
%token <string> STR
%token <string> NAME
%token <string> LABEL
%token LBRACKET RBRACKET LBRACE RBRACE LPAREN RPAREN HASH_LPAREN
%token BAR AND OR EOF

%start <Ast.statement list> program

%%

program:
  | statements = list(statement); EOF { statements }

statement:
  | head = NAME; args = nonempty_list(binding) { Directive (head, args) }
  | b = block                                  { Assert b }

binding:
  | label = LABEL; value = node { (label, value) }

(* :or binds looser than :and; both associate to the left. The
   grouping form is ordinary parentheses. *)
node:
  | left = node; OR; right = conjunction { Or (left, right) }
  | conj = conjunction                   { conj }

conjunction:
  | left = conjunction; AND; right = operand { And (left, right) }
  | operand = operand                        { operand }

operand:
  | b = block                     { b }
  | name = NAME                   { Name name }
  | n = INT                       { Int n }
  | r = RAT                       { Rat (fst r, snd r) }
  | s = STR                       { Str s }
  | LBRACE; fields = nonempty_list(binding); RBRACE { Record fields }
  | HASH_LPAREN; items = list(operand); tail = option(seq_tail); RPAREN
      { Seq (items, tail) }
  | LPAREN; n = node; RPAREN      { n }

seq_tail:
  | BAR; tail = operand { tail }

block:
  | LBRACKET; head = NAME; args = list(binding); RBRACKET { Block (head, args) }