summaryrefslogblamecommitdiff
path: root/frontend/parser.mly
blob: fb0047818849ecb826c82e414685d0590531f031 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

        
         

  
                    
            


                   
          

                         
          
                       
                                                  






                                            



                      
                       


          
                             







                                           
                

                              

  

                                 

         

                                                
 

             





                                                    
                                                               
                                                                   


                                        
                                                 
                                                              




                                                       



                                                           
                                                                         
                                                                              

                                                                                   






                              
                   





                           
                    

                            

        

                                                                         

     
                      

 
                                               

























                                                                              
    

                                                                    

                                                                       
                                                                    

    


                                                             
 
                  
      
                                                       


                                                     
                                                          
       

    
                                              









                                             





                                                       





                                                  
                                    

                                 






                                    

                                 
          







                                      


                                 
  
%{
open Ast
open Util
%}

%token BOOL INT REAL
%token PROBE
%token TRUE FALSE
%token IF THEN ELSE
%token NOT AND OR
%token MOD
%token CONST NODE RETURNS
%token VAR LET TEL
%token PRE
%token ASSUME GUARANTEE
%token AUTOMATON STATE INITIAL UNTIL UNLESS RESUME

%token LPAREN RPAREN
%token LCURLY RCURLY
%token STAR PLUS MINUS DIVIDE
%token LESS GREATER LESS_EQUAL GREATER_EQUAL
%token DIFF EQUAL
%token SEMICOLON COLON COMMA
%token ARROW

%token <string> IDENT
%token <string> INTVAL
%token <string> REALVAL

%token EOF

(* Lowest priorities first *)
%left ARROW
%left OR
%left AND
%left EQUAL DIFF
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left PLUS MINUS
%left STAR DIVIDE MOD

(* Root token *)
%start<Ast.toplevel list> file

%%

file:
| t=list(toplevel) EOF      { t }

toplevel:
| d=ext(const_decl)         { AST_const_decl d }
| d=ext(node_decl)          { AST_node_decl d }


primary_expr:
| LPAREN e=expr RPAREN      { e }
| e=ext(IDENT)              { AST_identifier e }
| e=ext(INTVAL)             { AST_int_const e }
| e=ext(REALVAL)            { AST_real_const e }
| TRUE                      { AST_bool_const true }
| FALSE                     { AST_bool_const false }
| e=ext(IDENT) LPAREN l=separated_list(COMMA,ext(expr)) RPAREN 
                            { AST_instance (e, l, fst e ^ uid ()) }

unary_expr:
| e=primary_expr                   { e }
| NOT e=ext(unary_expr)            { AST_not(e) }
| PRE e=ext(unary_expr)            { AST_pre(e, "pre"^uid()) }
| o=unary_op e=ext(unary_expr)     { AST_unary (o, e) }

%inline unary_op:
| PLUS          { AST_UPLUS }
| MINUS         { AST_UMINUS }


binary_expr:
| e=unary_expr                                        { e }
| e=ext(binary_expr) ARROW f=ext(binary_expr)         { AST_arrow(e, f) }
| e=ext(binary_expr) o=binary_op f=ext(binary_expr)   { AST_binary (o, e, f) }
| e=ext(binary_expr) o=binary_rel f=ext(binary_expr)  { AST_binary_rel (o, e, f) }
| e=ext(binary_expr) o=binary_bool f=ext(binary_expr) { AST_binary_bool (o, e, f) }

%inline binary_op:
| STAR           { AST_MUL }
| DIVIDE         { AST_DIV }
| MOD            { AST_MOD }
| PLUS           { AST_PLUS }
| MINUS          { AST_MINUS }
%inline binary_rel:
| LESS           { AST_LT }
| GREATER        { AST_GT }
| LESS_EQUAL     { AST_LE }
| GREATER_EQUAL  { AST_GE }
| EQUAL          { AST_EQ}
| DIFF           { AST_NE }
%inline binary_bool:
| AND            { AST_AND }
| OR             { AST_OR }

if_expr:
| IF c=ext(expr) THEN t=ext(expr) ELSE e=ext(expr)    { AST_if(c, t, e) }
| e=binary_expr                                       { e }

expr:
| e=if_expr      { e }


(* Equations (can be asserts, automata, ...) *)
automaton:
| AUTOMATON a=IDENT? s=list(ext(state)) RETURNS r=separated_list(COMMA, IDENT)
    { ((match a with Some n -> n | None -> "aut") ^ uid (), s, r) }

state:
| i=boption(INITIAL) STATE n=IDENT
  unless=trans(UNLESS)
  v=option(var_decl)
  b=body
  until=trans(UNTIL)
{ if unless <> [] then failwith "UNLESS transitions not supported.";
  { initial = i;
    name = n;
    locals = (match v with Some v -> v | None -> []);
    body = b;
    until = until;
} }

trans(TT):
| TT t=nonempty_list(terminated(transition, SEMICOLON))   { t }
|                                                         { [] }

transition:
| IF e=ext(expr) RESUME s=ext(IDENT)                      { (e, s) }


eqn:
| i=separated_list(COMMA, ext(IDENT)) EQUAL e=ext(expr)         
                                                { AST_assign(i, e) }
| ASSUME i=ext(IDENT) COLON e=ext(expr)         { AST_assume(i, e) }
| GUARANTEE i=ext(IDENT) COLON e=ext(expr)      { AST_guarantee(i, e) }
| a=automaton                                   { AST_automaton(a) }

typ:
| INT                                           { AST_TINT }
| BOOL                                          { AST_TBOOL }
| REAL                                          { AST_TREAL }

(* Declarations *)
dbody:
| e=ext(eqn) SEMICOLON                          { [e] }
| l=body                                        { l }

body:
| LET l=nonempty_list(terminated(ext(eqn), SEMICOLON)) TEL
  { l }

var:
|   p=boption(PROBE) i=ext(IDENT)   { (p, i) }

vari:
|   vn=separated_list(COMMA, var) COLON t=typ
    { List.map (fun (p, i) -> (p, i, t)) vn }

vars:
| v=separated_list(SEMICOLON, vari)
    { List.flatten v }

const_decl:
| CONST i=IDENT COLON t=typ EQUAL e=ext(expr) SEMICOLON
    { {
        name = i;
        typ = t;
        value = e;
    } }

var_decl:
| VAR l=nonempty_list(terminated(vari, SEMICOLON))
    { List.flatten l }

node_decl:
| NODE id=IDENT LPAREN v=vars RPAREN
    RETURNS LPAREN rv=vars RPAREN
    e = dbody
{ { name = id;
    args = v;
    ret = rv;
    var = [];
    body = e;
} }
| NODE id=IDENT LPAREN v=vars RPAREN
    RETURNS LPAREN rv=vars RPAREN
    lv=var_decl
    b=body
{ { name = id;
    args = v;
    ret = rv;
    var = lv;
    body = b;
} }

(* Utility : add extent information *)
%inline ext(X): 
| x=X { x, ($startpos, $endpos) }

%%