source: Deliverables/D2.2/8051/src/cminor/cminorParser.mly @ 1491

Last change on this file since 1491 was 818, checked in by ayache, 9 years ago

32 and 16 bits operations support in D2.2/8051

File size: 20.5 KB
Line 
1/* Adapted from Leroy's CompCert */
2/* TODO: check coherence with CminorPrinter */
3
4/* tokens ALLOC, DOLLAR, IN, LET, p_let were unused and have been removed */
5/* precedence levels unused were also removed */
6
7/* *********************************************************************/
8/*                                                                     */
9/*              The Compcert verified compiler                         */
10/*                                                                     */
11/*          Xavier Leroy, INRIA Paris-Rocquencourt                     */
12/*                                                                     */
13/*  Copyright Institut National de Recherche en Informatique et en     */
14/*  Automatique.  All rights reserved.  This file is distributed       */
15/*  under the terms of the GNU General Public License as published by  */
16/*  the Free Software Foundation, either version 2 of the License, or  */
17/*  (at your option) any later version.  This file is also distributed */
18/*  under the terms of the INRIA Non-Commercial License Agreement.     */
19/*                                                                     */
20/* *********************************************************************/
21
22%{
23
24  open AST
25  open Cminor
26  open Memory
27
28  let error_prefix = "Cminor parser"
29  let error s = Error.global_error error_prefix s
30  let warning s = Error.warning error_prefix s
31  let error_float () = error "float not supported."
32
33  let uint32 = (4, Unsigned)
34  let int32 = (4, Signed)
35
36  (* Function calls are not allowed in the AST of expressions, but function
37     calls in the AST of statements have a special argument which can be used to
38     store the result of the function call in a side-effect manner.
39     Example: the statement
40       x = y + f(z,g(t));
41     will be transformed into the (simplified syntax) AST statements
42       g(_t1,t)
43       f(_t2,y,_t1);
44       x = y + _t2
45     where _t1 and _t2 are fresh temporary variables. *)
46
47
48  (* Thus, to deal with function calls in expressions, we need to create fresh
49     temporary variables *)
50
51  let temp_counter = ref 0
52  let temporaries = ref []
53
54  let mktemp () =
55    incr temp_counter;
56    let id = Printf.sprintf "_t%d" !temp_counter in
57      temporaries := id :: !temporaries;
58      id
59
60
61  (* Expressions with function calls *)
62
63  type rexpr =
64    | RId of ident
65    | RCst of cst
66    | ROp1 of op1 * rexpr
67    | ROp2 of op2 * rexpr * rexpr
68    | RMem of Memory.quantity * rexpr
69    | RCond of rexpr * rexpr * rexpr
70    | RCall of rexpr * rexpr list * signature
71
72  (* [convert_accu] stores the function calls of expressions with function
73     calls being converted to expressions without function calls *)
74  let convert_accu = ref []
75
76  (* [convert_rexpr rexpr] converts the expression with function calls [rexpr]
77     into an expression without function calls. The function calls in [rexpr]
78     are stored in [convert_accu] *)
79  let rec convert_rexpr = function
80    | RId id -> Id id
81    | RCst c -> Cst c
82    | ROp1 (op, e1) -> Op1 (op, convert_rexpr e1)
83    | ROp2 (op, e1, e2) -> Op2 (op, convert_rexpr e1, convert_rexpr e2)
84    | RMem (chunk, e1) -> Mem (chunk, convert_rexpr e1)
85    | RCond (e1, e2, e3) ->
86        Cond (convert_rexpr e1, convert_rexpr e2, convert_rexpr e3)
87    | RCall(e1, el, sg) ->
88        let c1 = convert_rexpr e1 in
89        let cl = convert_rexpr_list el in
90        let t = mktemp() in
91          convert_accu := St_call (Some t, c1, cl, sg) :: !convert_accu;
92          Id t
93
94  and convert_rexpr_list el = List.map convert_rexpr el
95
96  (* [prepend_seq stmts last] reverses and sequences the list of statements
97     [stmts] and puts [last] at the end *)
98  let rec prepend_seq stmts last =
99    match stmts with
100      | [] -> last
101      | s1 :: sl -> prepend_seq sl (St_seq (s1, last))
102
103  (* [mkeval e] creates the AST statement associated to the Cminor instruction
104       e;
105     where [e] is an expression with possible function calls *)
106  let mkeval e =
107    convert_accu := [];
108    match e with
109      | RCall (e1, el, sg) ->
110          let c1 = convert_rexpr e1 in
111          let cl = convert_rexpr_list el in
112            prepend_seq !convert_accu (St_call (None, c1, cl, sg))
113      | _ ->
114          ignore (convert_rexpr e);
115          prepend_seq !convert_accu St_skip
116
117  (* [mkeval id e] creates the AST statement associated to the Cminor
118     instruction
119       id = e;
120     where [e] is an expression with possible function calls *)
121  let mkassign id e =
122    convert_accu := [];
123    match e with
124      | RCall (e1, el, sg) ->
125          let c1 = convert_rexpr e1 in
126          let cl = convert_rexpr_list el in
127            prepend_seq !convert_accu (St_call (Some id, c1, cl, sg))
128      | _ ->
129          let c = convert_rexpr e in
130            prepend_seq !convert_accu (St_assign (id, c))
131
132  (* [mkstore size e1 e2] creates the AST statement associated to the Cminor
133     instruction
134       size[e1] = e2;
135     where [e1] and [e2] are expressions with possible function calls *)
136  let mkstore size e1 e2 =
137    convert_accu := [];
138    let c1 = convert_rexpr e1 in
139    let c2 = convert_rexpr e2 in
140      prepend_seq !convert_accu (St_store (size, c1, c2))
141
142  (* [mkifthenelse e s1 s2] creates the AST statement associated to the Cminor
143     instruction
144       if (e) { s1 } else { s2 }
145     where [e] is an expression with possible function calls *)
146  let mkifthenelse e s1 s2 =
147    convert_accu := [];
148    let c = convert_rexpr e in
149      prepend_seq !convert_accu (St_ifthenelse (c, s1, s2))
150
151  (* [mkreturn_some e] creates the AST statement associated to the Cminor
152     instruction
153       return e;
154     where [e] is an expression with possible function calls *)
155  let mkreturn_some e =
156    convert_accu := [];
157    let c = convert_rexpr e in
158      prepend_seq !convert_accu (St_return (Some c))
159
160  (* [mkswitch e (cases, dfl)] creates the AST statement associated to the
161     Cminor instruction
162       switch (e) {
163         case i: exit j_i;
164         ...
165         default: exit j_default; }
166     where [e] is an expression with possible function calls *)
167  let mkswitch e (cases, dfl) =
168    convert_accu := [];
169    let c = convert_rexpr e in
170      prepend_seq !convert_accu (St_switch (c, cases, dfl))
171
172  (* The Cminor instruction
173      match (e) {
174        case 0: s0;
175        case 1: s1;
176        case 2: s2; }
177     is syntaxic sugar for the Cminor instruction
178       block {
179         block {
180           block {
181             block {
182               switch (e) {
183                 case 0: exit 0;
184                 case 1: exit 1;
185                 default: exit 2; }
186             } s0; exit 2;
187           } s1; exit 1;
188         } s2;
189       }
190     Note that matches are assumed to be exhaustive *)
191
192  let mkmatch_aux e cases =
193    let ncases = List.length cases in
194    let rec mktable n = function
195      | [] -> assert false
196      | [key, action] -> []
197      | (key, action) :: rem -> (key, n) :: mktable (n+1) rem in
198    let sw =
199      St_switch (e, mktable 0 cases, pred ncases) in
200    let rec mkblocks body n = function
201      | [] -> assert false
202      | [key, action] -> St_block (St_seq (body, action))
203      | (key, action) :: rem ->
204          mkblocks
205            (St_block (St_seq (body, St_seq (action, St_exit n))))
206            (pred n) rem in
207      mkblocks (St_block sw) (pred ncases) cases
208
209  (* [mkmatch e cases] creates the AST statement associated to the Cminor
210     instruction
211       match (e) {
212         case i: s_i;
213         ... }
214     where [e] is an expression with possible function calls *)
215  let mkmatch e cases =
216    convert_accu := [];
217    let c = convert_rexpr e in
218    let s =
219      match cases with
220        | [] -> St_skip (* ??? *)
221        | [key, action] -> action
222        | _ -> mkmatch_aux c cases in
223      prepend_seq !convert_accu s
224
225  (* [mktailcall f [e1;e2;...] sig] creates the AST statement associated to the
226     Cminor instruction
227     tailcall f(e1,e2,...): sig
228     where [e], [e1], [e2], ... are expressions with possible function calls *)
229  let mktailcall e1 el sg =
230    convert_accu := [];
231    let c1 = convert_rexpr e1 in
232    let cl = convert_rexpr_list el in
233      prepend_seq !convert_accu (St_tailcall (c1, cl, sg))
234
235  (* Parse error handler *)
236  let raise_error (_, pos) s = Error.error "parse error" pos (s ^ "\n")
237
238%}
239
240%token ABSF
241%token AMPERSAND
242%token AMPERSANDAMPERSAND
243%token BANG
244%token BANGEQUAL
245%token BANGEQUALF
246%token BANGEQUALU
247%token BAR
248%token BARBAR
249%token CARET
250%token CASE
251%token COLON
252%token COMMA
253%token DEFAULT
254%token ELSE
255%token EQUAL
256%token EQUALEQUAL
257%token EQUALEQUALF
258%token EQUALEQUALU
259%token EOF
260%token EXIT
261%token EXTERN
262%token FLOAT
263%token FLOAT32
264%token FLOAT64
265%token <float> FLOATLIT
266%token FLOATOFINT
267%token FLOATOFINTU
268%token GREATER
269%token GREATERF
270%token GREATERU
271%token GREATEREQUAL
272%token GREATEREQUALF
273%token GREATEREQUALU
274%token GREATERGREATER
275%token GREATERGREATERU
276%token <string> IDENT
277%token IF
278%token INT
279%token INT8
280%token INT16
281%token INT32
282%token INT8STO8
283%token INT8STO16
284%token INT8STO32
285%token INT8UTO8
286%token INT8UTO16
287%token INT8UTO32
288%token INT16STO8
289%token INT16STO16
290%token INT16STO32
291%token INT16UTO8
292%token INT16UTO16
293%token INT16UTO32
294%token INT32STO8
295%token INT32STO16
296%token INT32STO32
297%token INT32UTO8
298%token INT32UTO16
299%token INT32UTO32
300%token <int> INTLIT
301%token INTOFFLOAT
302%token INTUOFFLOAT
303%token LBRACE
304/* %token LBRACELBRACE */
305%token LBRACKET
306%token LESS
307%token LESSU
308%token LESSF
309%token LESSEQUAL
310%token LESSEQUALU
311%token LESSEQUALF
312%token LESSLESS
313%token LOOP
314%token LPAREN
315%token MATCH
316%token MINUS
317%token MINUSF
318%token MINUSGREATER
319%token PERCENT
320%token PERCENTU
321%token PLUS
322%token PLUSF
323%token QUESTION
324%token RBRACE
325/* %token RBRACERBRACE */
326%token RBRACKET
327%token RETURN
328%token RPAREN
329%token SEMICOLON
330%token SLASH
331%token SLASHF
332%token SLASHU
333%token STACK
334%token STAR
335%token STARF
336%token <string> STRINGLIT
337%token SWITCH
338%token TILDE
339%token TAILCALL
340%token VAR
341%token VOID
342%token GOTO BLOCK
343%token PTR
344
345/* Unused */
346/* %token ALLOC DOLLAR IN LET p_let */
347
348/* Precedences from low to high */
349
350/* %left COMMA */
351/* %left p_let */
352/* %right EQUAL */
353%right QUESTION COLON
354%left BARBAR
355%left AMPERSANDAMPERSAND
356%left BAR
357%left CARET
358%left AMPERSAND
359%left EQUALEQUAL BANGEQUAL LESS LESSEQUAL GREATER GREATEREQUAL EQUALEQUALU BANGEQUALU LESSU LESSEQUALU GREATERU GREATEREQUALU EQUALEQUALF BANGEQUALF LESSF LESSEQUALF GREATERF GREATEREQUALF
360%left LESSLESS GREATERGREATER GREATERGREATERU
361%left PLUS PLUSF MINUS MINUSF
362%left STAR SLASH PERCENT STARF SLASHF SLASHU PERCENTU
363%nonassoc BANG TILDE p_uminus ABSF INTOFFLOAT INTUOFFLOAT FLOATOFINT FLOATOFINTU FLOAT32 /* ALLOC */
364%left LPAREN
365
366/* Entry point */
367
368%start program
369%type <Cminor.program> program
370
371%%
372
373%inline position(X): x = X { (x, Position.lex_join $startpos $endpos) }
374
375/* Programs */
376
377program:
378    global_declarations proc_list EOF { { vars   = List.rev $1 ;
379                                          functs = List.rev $2 ;
380                                          main   = Some "main" } }
381;
382
383global_declarations:
384    /* empty */                            { [] }
385  | global_declarations global_declaration { $2 :: $1 }
386;
387
388global_declaration:
389    VAR STRINGLIT init_datas { ($2, List.rev $3) }
390  | pos = position(error)    { raise_error pos
391                                 "Global declaration syntax error" }
392;
393
394init_datas:
395    /* empty */                  { [] }
396  | init_data                    { [$1] }
397  | LBRACE init_data_list RBRACE { $2 }
398;
399
400init_data:
401    INTLIT                         { AST.Data_int32 $1 }
402  | FLOATLIT                       { AST.Data_float32 $1 }
403  | LPAREN INT8 RPAREN INTLIT      { AST.Data_int8 $4 }
404  | LPAREN INT16 RPAREN INTLIT     { AST.Data_int16 $4 }
405  | LPAREN INT32 RPAREN INTLIT     { AST.Data_int32 $4 }
406  | LPAREN FLOAT32 RPAREN FLOATLIT { AST.Data_float32 $4 }
407  | LPAREN FLOAT64 RPAREN FLOATLIT { AST.Data_float64 $4 }
408  | LBRACKET INTLIT RBRACKET       { AST.Data_reserve $2 }
409;
410
411quantity:
412    INTLIT { Memory.QInt $1 }
413  | PTR    { Memory.QPtr }
414
415init_data_list:
416    init_data                      { [$1] }
417  | init_data COMMA init_data_list { $1 :: $3 }
418;
419
420proc_list:
421    /* empty */    { [] }
422  | proc_list proc { $2 :: $1 }
423;
424
425/* Procedures */
426
427proc:
428    STRINGLIT LPAREN parameters RPAREN COLON signature
429    LBRACE
430      stack_declaration
431      var_declarations
432      stmt_list
433    RBRACE
434  { let tmp = !temporaries in
435      temporaries := [];
436      temp_counter := 0;
437      ($1, F_int { f_sig = $6 ;
438                   f_params = List.rev $3 ;
439                   f_vars = List.rev (tmp @ $9) ;
440                   f_ptrs = [] (* TODO *) ;
441                   f_stacksize = $8 ;
442                   f_body = $10 }) }
443  | EXTERN STRINGLIT COLON signature { ($2, F_ext { ef_tag = $2 ;
444                                                    ef_sig = $4 }) }
445  | pos = position(error) { raise_error pos
446                            "Procedure or function declaration syntax error" }
447;
448
449parameters:
450    /* empty */    { [] }
451  | parameter_list { $1 }
452;
453
454parameter_list:
455    IDENT                      { $1 :: [] }
456  | parameter_list COMMA IDENT { $3 :: $1 }
457  | pos = position(error) { raise_error pos
458                            "Parameter declaration syntax error" }
459;
460
461signature:
462    type_  { { args = [] ; res = Type_ret $1 } }
463  | VOID
464      { { args = [] ; res = Type_void } }
465  | type_ MINUSGREATER signature
466          { let s = $3 in {s with args = $1 :: s.args } }
467  | pos = position(error) { raise_error pos "Signature syntax error" }
468;
469
470stack_declaration:
471    /* empty */            { 0 }
472  | STACK INTLIT SEMICOLON { $2 }
473  | pos = position(error)  { raise_error pos "Stack declaration syntax error" }
474;
475
476var_declarations:
477    /* empty */                      { [] }
478  | var_declarations var_declaration { $2 @ $1 }
479  | pos = position(error)            { raise_error pos
480                                         "Variable declaration syntax error" }
481;
482
483var_declaration:
484    VAR parameter_list SEMICOLON { $2 }
485;
486
487/* Statements */
488
489stmt:
490    expr SEMICOLON                         { mkeval $1 }
491  | IDENT EQUAL expr SEMICOLON             { mkassign $1 $3 }
492  | quantity LBRACKET expr RBRACKET EQUAL expr SEMICOLON
493      { mkstore $1 $3 $6 }
494  | IF LPAREN expr RPAREN stmts ELSE stmts { mkifthenelse $3 $5 $7 }
495  | IF LPAREN expr RPAREN stmts            { mkifthenelse $3 $5 St_skip }
496  | LOOP stmts                             { St_loop $2 }
497  | BLOCK LBRACE stmt_list RBRACE          { St_block $3 }
498  | EXIT SEMICOLON                         { St_exit 0 }
499  | EXIT INTLIT SEMICOLON                  { St_exit $2 }
500  | RETURN SEMICOLON                       { St_return None }
501  | RETURN expr SEMICOLON                  { mkreturn_some $2 }
502  | GOTO IDENT SEMICOLON                   { St_goto $2 }
503  | IDENT COLON stmt                       { St_label ($1, $3) }
504  | SWITCH LPAREN expr RPAREN LBRACE switch_cases RBRACE
505        { mkswitch $3 $6 }
506  | MATCH LPAREN expr RPAREN LBRACE match_cases RBRACE
507          { mkmatch $3 $6 }
508  | TAILCALL expr LPAREN expr_list RPAREN COLON signature SEMICOLON
509              { mktailcall $2 $4 $7 }
510;
511
512stmt_list:
513    /* empty */    { St_skip }
514  | stmt stmt_list { St_seq ($1, $2) }
515  | pos = position(error) { raise_error pos "Statement syntax error" }
516;
517
518stmts:
519    LBRACE stmt_list RBRACE { $2 }
520  | stmt                    { $1 }
521;
522
523switch_cases:
524    DEFAULT COLON EXIT INTLIT SEMICOLON
525    { ([], $4) }
526  | CASE INTLIT COLON EXIT INTLIT SEMICOLON switch_cases
527        { let (cases, dfl) = $7 in (($2, $5) :: cases, dfl) }
528  | pos = position(error) { raise_error pos "Syntax error in switch construct" }
529;
530
531match_cases:
532    /* empty */                             { [] }
533  | CASE INTLIT COLON stmt_list match_cases { ($2, $4) :: $5 }
534  | pos = position(error) { raise_error pos "Syntax error in match construct" }
535;
536
537/* Expressions */
538
539expr:
540    LPAREN expr RPAREN                      { $2 }
541  | IDENT                               { RId $1 }
542  | INTLIT                              { RCst (Cst_int $1) }
543  | FLOATLIT                            { RCst (Cst_float $1) }
544  | STRINGLIT                           { RCst (Cst_addrsymbol $1) }
545  | AMPERSAND INTLIT                    { RCst (Cst_stackoffset $2) }
546  | MINUS expr    %prec p_uminus        { ROp1 (Op_negint int32, $2) }
547  | MINUSF expr   %prec p_uminus        { error_float () }
548  | ABSF expr                           { error_float () }
549  | INTOFFLOAT expr                     { error_float () }
550  | INTUOFFLOAT expr                    { error_float () }
551  | FLOATOFINT expr                     { error_float () }
552  | FLOATOFINTU expr                    { error_float () }
553  | TILDE expr                          { ROp1 (Op_notint int32, $2) }
554  | BANG expr                           { ROp1 (Op_notbool, $2) }
555  | INT8STO8 expr                       { ROp1 (Op_cast ((8, Signed), 8), $2) }
556  | INT8STO16 expr                      { ROp1 (Op_cast ((8, Signed), 16), $2) }
557  | INT8STO32 expr                      { ROp1 (Op_cast ((8, Signed), 32), $2) }
558  | INT8UTO8 expr                      { ROp1 (Op_cast ((8, Unsigned), 8), $2) }
559  | INT8UTO16 expr                    { ROp1 (Op_cast ((8, Unsigned), 16), $2) }
560  | INT8UTO32 expr                    { ROp1 (Op_cast ((8, Unsigned), 32), $2) }
561  | INT16STO8 expr                     { ROp1 (Op_cast ((16, Signed), 16), $2) }
562  | INT16STO16 expr                    { ROp1 (Op_cast ((16, Signed), 16), $2) }
563  | INT16STO32 expr                    { ROp1 (Op_cast ((16, Signed), 32), $2) }
564  | INT16UTO8 expr                    { ROp1 (Op_cast ((16, Unsigned), 8), $2) }
565  | INT16UTO16 expr                  { ROp1 (Op_cast ((16, Unsigned), 16), $2) }
566  | INT16UTO32 expr                  { ROp1 (Op_cast ((16, Unsigned), 32), $2) }
567  | INT32STO8 expr                      { ROp1 (Op_cast ((32, Signed), 8), $2) }
568  | INT32STO16 expr                    { ROp1 (Op_cast ((32, Signed), 16), $2) }
569  | INT32STO32 expr                    { ROp1 (Op_cast ((32, Signed), 32), $2) }
570  | INT32UTO8 expr                    { ROp1 (Op_cast ((32, Unsigned), 8), $2) }
571  | INT32UTO16 expr                  { ROp1 (Op_cast ((32, Unsigned), 16), $2) }
572  | INT32UTO32 expr                  { ROp1 (Op_cast ((32, Unsigned), 32), $2) }
573  | FLOAT32 expr                        { error_float () }
574  | expr PLUS expr                      { ROp2 (Op_add int32, $1, $3) }
575  | expr MINUS expr                     { ROp2 (Op_sub int32, $1, $3) }
576  | expr STAR expr                      { ROp2 (Op_mul int32, $1, $3) }
577  | expr SLASH expr                     { ROp2 (Op_div int32, $1, $3) }
578  | expr PERCENT expr                   { ROp2 (Op_mod int32, $1, $3) }
579  | expr SLASHU expr                    { ROp2 (Op_div uint32, $1, $3) }
580  | expr PERCENTU expr                  { ROp2 (Op_mod uint32, $1, $3) }
581  | expr AMPERSAND expr                 { ROp2 (Op_and, $1, $3) }
582  | expr BAR expr                       { ROp2 (Op_or, $1, $3) }
583  | expr CARET expr                     { ROp2 (Op_xor, $1, $3) }
584  | expr LESSLESS expr                  { ROp2 (Op_shl int32, $1, $3) }
585  | expr GREATERGREATER expr            { ROp2 (Op_shr int32, $1, $3) }
586  | expr GREATERGREATERU expr           { ROp2 (Op_shr uint32, $1, $3) }
587  | expr PLUSF expr                     { error_float () }
588  | expr MINUSF expr                    { error_float () }
589  | expr STARF expr                     { error_float () }
590  | expr SLASHF expr                    { error_float () }
591  | expr EQUALEQUAL expr               { ROp2 (Op_cmp (Cmp_eq, int32), $1, $3) }
592  | expr BANGEQUAL expr                { ROp2 (Op_cmp (Cmp_ne, int32), $1, $3) }
593  | expr LESS expr                     { ROp2 (Op_cmp (Cmp_lt, int32), $1, $3) }
594  | expr LESSEQUAL expr                { ROp2 (Op_cmp (Cmp_le, int32), $1, $3) }
595  | expr GREATER expr                  { ROp2 (Op_cmp (Cmp_gt, int32), $1, $3) }
596  | expr GREATEREQUAL expr             { ROp2 (Op_cmp (Cmp_ge, int32), $1, $3) }
597  | expr EQUALEQUALU expr             { ROp2 (Op_cmp (Cmp_eq, uint32), $1, $3) }
598  | expr BANGEQUALU expr              { ROp2 (Op_cmp (Cmp_ne, uint32), $1, $3) }
599  | expr LESSU expr                   { ROp2 (Op_cmp (Cmp_lt, uint32), $1, $3) }
600  | expr LESSEQUALU expr              { ROp2 (Op_cmp (Cmp_le, uint32), $1, $3) }
601  | expr GREATERU expr                { ROp2 (Op_cmp (Cmp_gt, uint32), $1, $3) }
602  | expr GREATEREQUALU expr           { ROp2 (Op_cmp (Cmp_ge, uint32), $1, $3) }
603  | expr EQUALEQUALF expr               { error_float () }
604  | expr BANGEQUALF expr                { error_float () }
605  | expr LESSF expr                     { error_float () }
606  | expr LESSEQUALF expr                { error_float () }
607  | expr GREATERF expr                  { error_float () }
608  | expr GREATEREQUALF expr             { error_float () }
609  | quantity LBRACKET expr RBRACKET       { RMem ($1, $3) }
610  | expr AMPERSANDAMPERSAND expr        { RCond ($1, $3, RCst (Cst_int 0)) }
611  | expr BARBAR expr                    { RCond ($1, RCst (Cst_int 1), $3) }
612  | expr QUESTION expr COLON expr       { RCond ($1, $3, $5) }
613  | expr LPAREN expr_list RPAREN COLON signature
614      { RCall ($1, $3, $6) }
615  | pos = position(error) { raise_error pos "Expression syntax error" }
616;
617
618expr_list:
619    /* empty */ { [] }
620  | expr_list_1 { $1 }
621;
622
623expr_list_1:
624    expr /* %prec COMMA */ { $1 :: [] }
625  | expr COMMA expr_list_1 { $1 :: $3 }
626;
627
628type_:
629    INT   { Sig_int }
630  | FLOAT { Sig_float }
631;
632
Note: See TracBrowser for help on using the repository browser.