2022-12-07 16:45:55 +01:00
|
|
|
%{
|
2022-12-09 17:01:04 +01:00
|
|
|
open Ast
|
2022-12-09 14:26:28 +01:00
|
|
|
exception MyParsingError of string
|
|
|
|
|
2022-12-07 16:45:55 +01:00
|
|
|
let current_location () = symbol_start_pos (), symbol_end_pos ()
|
2022-12-09 14:26:28 +01:00
|
|
|
|
2022-12-09 17:01:04 +01:00
|
|
|
let defined_nodes : (ident, t_node) Hashtbl.t = Hashtbl.create 100
|
2022-12-09 14:26:28 +01:00
|
|
|
|
2022-12-09 17:01:04 +01:00
|
|
|
let defined_vars : (ident, t_var) Hashtbl.t = Hashtbl.create 100
|
2022-12-09 14:26:28 +01:00
|
|
|
|
2022-12-09 17:01:04 +01:00
|
|
|
let fetch_node (n: ident) =
|
2022-12-09 14:26:28 +01:00
|
|
|
match Hashtbl.find_opt defined_nodes n with
|
|
|
|
| None ->
|
|
|
|
raise (MyParsingError
|
2022-12-09 15:47:27 +01:00
|
|
|
("The node "^n^" does not exist."))
|
2022-12-09 14:26:28 +01:00
|
|
|
| Some node -> node
|
|
|
|
|
2022-12-09 17:01:04 +01:00
|
|
|
let fetch_var (n: ident) : t_var =
|
2022-12-09 14:26:28 +01:00
|
|
|
match Hashtbl.find_opt defined_vars n with
|
|
|
|
| None ->
|
|
|
|
raise (MyParsingError
|
2022-12-09 15:47:27 +01:00
|
|
|
("The var "^n^" does not exist."))
|
2022-12-09 14:26:28 +01:00
|
|
|
| Some var -> var
|
|
|
|
|
2022-12-09 17:01:04 +01:00
|
|
|
let type_var (v: t_var) =
|
|
|
|
match v with
|
|
|
|
| IVar _ -> FTBase TInt
|
|
|
|
| BVar _ -> FTBase TBool
|
|
|
|
| RVar _ -> FTBase TReal
|
|
|
|
|
|
|
|
let type_exp : t_expression -> full_ty = function
|
|
|
|
| EVar (full_ty , _) -> full_ty
|
|
|
|
| EMonOp (full_ty , _ , _) -> full_ty
|
|
|
|
| EBinOp (full_ty , _ , _ , _) -> full_ty
|
|
|
|
| ETriOp (full_ty , _ , _ , _ , _) -> full_ty
|
|
|
|
| EComp (full_ty , _ , _ , _) -> full_ty
|
|
|
|
| EWhen (full_ty , _ , _) -> full_ty
|
|
|
|
| EConst (full_ty , _) -> full_ty
|
|
|
|
| ETuple (full_ty , _) -> full_ty
|
|
|
|
| EApp (full_ty , _ , _) -> full_ty
|
|
|
|
|
2022-12-09 16:33:07 +01:00
|
|
|
let concat_varlist (t1, e1) (t2, e2) =
|
2022-12-09 17:01:04 +01:00
|
|
|
(
|
2022-12-09 16:33:07 +01:00
|
|
|
match t1, t2 with
|
|
|
|
| FTList lt1, FTList lt2 -> (FTList (lt1 @ lt2), e1@e2)
|
|
|
|
| _ ->
|
|
|
|
raise (MyParsingError "This exception should not have been raised."))
|
|
|
|
|
2022-12-09 17:01:04 +01:00
|
|
|
let make_ident (v : t_var) : t_varlist =
|
2022-12-09 16:33:07 +01:00
|
|
|
match v with
|
2022-12-09 17:01:04 +01:00
|
|
|
| IVar _ -> (FTList [FTBase TInt ], [v])
|
|
|
|
| BVar _ -> (FTList [FTBase TBool], [v])
|
|
|
|
| RVar _ -> (FTList [FTBase TReal], [v])
|
2022-12-09 16:33:07 +01:00
|
|
|
|
2022-12-09 17:01:04 +01:00
|
|
|
let add_ident (v : t_var) (l: t_varlist) : t_varlist =
|
2022-12-09 16:33:07 +01:00
|
|
|
match v, l with
|
2022-12-09 17:01:04 +01:00
|
|
|
| IVar _, (FTList tl, l) -> (FTList (FTBase TInt :: tl), v :: l)
|
|
|
|
| BVar _, (FTList tl, l) -> (FTList (FTBase TBool :: tl), v :: l)
|
|
|
|
| RVar _, (FTList tl, l) -> (FTList (FTBase TReal :: tl), v :: l)
|
2022-12-09 16:33:07 +01:00
|
|
|
| _ -> raise (MyParsingError "This exception should not have been raised.")
|
2022-12-07 16:45:55 +01:00
|
|
|
%}
|
|
|
|
|
|
|
|
%token EOF
|
|
|
|
%token<string> IDENT
|
|
|
|
%token LPAREN
|
|
|
|
%token RPAREN
|
|
|
|
%token RETURNS
|
|
|
|
%token SEMICOL
|
|
|
|
%token COLON
|
|
|
|
%token BOOL
|
|
|
|
%token INT
|
|
|
|
%token LET
|
|
|
|
%token TEL
|
|
|
|
%token NODE
|
|
|
|
%token VAR
|
|
|
|
%token EQUAL
|
|
|
|
%token COMMA
|
2022-12-09 14:26:28 +01:00
|
|
|
%token<Ast.base_ty> TYP
|
2022-12-07 21:56:38 +01:00
|
|
|
|
|
|
|
%token MO_not
|
2022-12-09 14:26:28 +01:00
|
|
|
%token MO_pre
|
|
|
|
%token PLUS
|
|
|
|
%token MINUS
|
2022-12-07 21:56:38 +01:00
|
|
|
%token BO_and
|
|
|
|
%token BO_or
|
|
|
|
%token BO_mul
|
|
|
|
%token BO_div
|
2022-12-09 14:26:28 +01:00
|
|
|
%token BO_mod
|
|
|
|
%token BO_arrow
|
|
|
|
%token CMP_le
|
|
|
|
%token CMP_lt
|
|
|
|
%token CMP_ge
|
|
|
|
%token CMP_gt
|
|
|
|
%token CMP_neq
|
|
|
|
%token TO_merge
|
2022-12-07 21:56:38 +01:00
|
|
|
|
2022-12-09 14:26:28 +01:00
|
|
|
%token WHEN
|
2022-12-07 21:56:38 +01:00
|
|
|
|
|
|
|
%token IF
|
|
|
|
%token THEN
|
|
|
|
%token ELSE
|
|
|
|
|
|
|
|
%token<int> CONST_INT
|
|
|
|
%token<bool> CONST_BOOL
|
2022-12-09 14:26:28 +01:00
|
|
|
%token<Ast.real> CONST_REAL
|
2022-12-07 16:45:55 +01:00
|
|
|
|
|
|
|
/* The Entry Point */
|
|
|
|
%start main
|
2022-12-09 14:26:28 +01:00
|
|
|
%type <Ast.t_nodelist> main
|
2022-12-07 16:45:55 +01:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
main: nodes EOF { $1 };
|
|
|
|
|
|
|
|
nodes:
|
|
|
|
| /* empty */ { [] }
|
|
|
|
| node nodes { $1 :: $2 };
|
|
|
|
|
|
|
|
node:
|
2022-12-09 14:26:28 +01:00
|
|
|
NODE node_content { (* Flush known variables *) Hashtbl.clear defined_vars; $2 }
|
|
|
|
|
|
|
|
node_content:
|
|
|
|
IDENT LPAREN in_params RPAREN
|
2022-12-07 16:45:55 +01:00
|
|
|
RETURNS LPAREN out_params RPAREN SEMICOL
|
|
|
|
local_params
|
|
|
|
LET equations TEL
|
2022-12-09 15:47:27 +01:00
|
|
|
{ let node_name = $1 in
|
2022-12-09 16:33:07 +01:00
|
|
|
let (t_in, e_in) = $3 in
|
|
|
|
let (t_out, e_out) = $7 in
|
2022-12-09 15:47:27 +01:00
|
|
|
let n: Ast.t_node =
|
|
|
|
{ n_name = node_name;
|
2022-12-09 16:33:07 +01:00
|
|
|
n_inputs = (t_in, e_in);
|
|
|
|
n_outputs = (t_out, e_out);
|
2022-12-09 15:47:27 +01:00
|
|
|
n_local_vars = $10;
|
2022-12-09 16:33:07 +01:00
|
|
|
n_equations = $12;
|
|
|
|
n_type = FTArr (t_in, t_out); } in
|
2022-12-09 15:47:27 +01:00
|
|
|
Hashtbl.add defined_nodes node_name n; n
|
2022-12-07 16:45:55 +01:00
|
|
|
} ;
|
|
|
|
|
|
|
|
in_params:
|
2022-12-09 16:33:07 +01:00
|
|
|
| /* empty */ { (FTList [], []) }
|
2022-12-07 16:45:55 +01:00
|
|
|
| param_list { $1 }
|
2022-12-09 14:26:28 +01:00
|
|
|
;
|
2022-12-07 16:45:55 +01:00
|
|
|
|
|
|
|
out_params: param_list { $1 } ;
|
|
|
|
|
|
|
|
local_params:
|
2022-12-09 16:33:07 +01:00
|
|
|
| /* empty */ { (FTList [], []) }
|
2022-12-07 16:45:55 +01:00
|
|
|
| VAR param_list_semicol { $2 }
|
|
|
|
;
|
|
|
|
|
|
|
|
param_list_semicol:
|
2022-12-09 15:47:27 +01:00
|
|
|
| param SEMICOL { $1 }
|
2022-12-09 16:33:07 +01:00
|
|
|
| param SEMICOL param_list_semicol { concat_varlist $1 $3 }
|
2022-12-07 16:45:55 +01:00
|
|
|
|
|
|
|
param_list:
|
|
|
|
| param { $1 }
|
2022-12-09 16:33:07 +01:00
|
|
|
| param SEMICOL param_list { concat_varlist $1 $3 }
|
2022-12-07 16:45:55 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
param:
|
2022-12-09 14:26:28 +01:00
|
|
|
ident_comma_list COLON TYP
|
|
|
|
{ let typ = $3 in
|
|
|
|
let idents = $1 in
|
|
|
|
Ast.(
|
2022-12-09 16:33:07 +01:00
|
|
|
(FTList
|
|
|
|
(List.map
|
|
|
|
(fun t -> FTBase t) (Utils.list_repeat (List.length idents) typ)),
|
2022-12-09 14:26:28 +01:00
|
|
|
match typ with
|
|
|
|
| TBool ->
|
2022-12-09 16:33:07 +01:00
|
|
|
List.map (fun s -> Hashtbl.add defined_vars s (BVar s); BVar s) idents
|
2022-12-09 14:26:28 +01:00
|
|
|
| TReal ->
|
2022-12-09 16:33:07 +01:00
|
|
|
List.map (fun s -> Hashtbl.add defined_vars s (RVar s); RVar s) idents
|
2022-12-09 14:26:28 +01:00
|
|
|
| TInt ->
|
2022-12-09 16:33:07 +01:00
|
|
|
List.map (fun s -> Hashtbl.add defined_vars s (IVar s); IVar s) idents)) }
|
2022-12-07 16:45:55 +01:00
|
|
|
;
|
|
|
|
|
2022-12-09 14:26:28 +01:00
|
|
|
ident_comma_list:
|
|
|
|
| IDENT { [$1] }
|
|
|
|
| IDENT COMMA ident_comma_list { $1 :: $3 }
|
|
|
|
|
2022-12-07 16:45:55 +01:00
|
|
|
equations:
|
|
|
|
| /* empty */ { [] }
|
|
|
|
| equation SEMICOL equations
|
2022-12-09 15:47:27 +01:00
|
|
|
{ $1 :: $3 }
|
2022-12-07 16:45:55 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
equation:
|
|
|
|
pattern EQUAL expr
|
2022-12-09 14:26:28 +01:00
|
|
|
{ ($1, $3) }
|
2022-12-07 16:45:55 +01:00
|
|
|
;
|
|
|
|
|
2022-12-07 21:56:38 +01:00
|
|
|
pattern:
|
2022-12-09 16:33:07 +01:00
|
|
|
| IDENT
|
|
|
|
{ let v = fetch_var $1 in
|
2022-12-09 17:01:04 +01:00
|
|
|
Ast.(FTList [type_var v], [v])
|
|
|
|
}
|
2022-12-09 14:26:28 +01:00
|
|
|
| LPAREN ident_comma_list_patt RPAREN { $2 };
|
2022-12-07 21:56:38 +01:00
|
|
|
|
2022-12-09 14:26:28 +01:00
|
|
|
ident_comma_list_patt:
|
2022-12-09 16:33:07 +01:00
|
|
|
| IDENT { make_ident (fetch_var $1) }
|
|
|
|
| IDENT COMMA ident_comma_list_patt { add_ident (fetch_var $1) $3 }
|
2022-12-07 21:56:38 +01:00
|
|
|
|
|
|
|
expr:
|
2022-12-09 14:26:28 +01:00
|
|
|
/* Note: EQUAL does not follow the nomenclature CMP_, ... */
|
2022-12-07 21:56:38 +01:00
|
|
|
| LPAREN expr RPAREN { $2 }
|
2022-12-09 17:01:04 +01:00
|
|
|
| IDENT { let v = fetch_var $1 in EVar (type_var v, v) }
|
2022-12-09 14:26:28 +01:00
|
|
|
/* Unary operators */
|
2022-12-09 17:01:04 +01:00
|
|
|
| MO_not expr { EMonOp (type_exp $2, MOp_not, $2) }
|
|
|
|
| MO_pre expr { EMonOp (type_exp $2, MOp_pre, $2) }
|
|
|
|
| MINUS expr { EMonOp (type_exp $2, MOp_minus, $2) }
|
2022-12-09 14:26:28 +01:00
|
|
|
| PLUS expr { $2 }
|
|
|
|
/* Binary operators */
|
2022-12-09 17:01:04 +01:00
|
|
|
| expr PLUS expr { EBinOp (type_exp $1, BOp_add, $1, $3) }
|
|
|
|
| expr MINUS expr { EBinOp (type_exp $1, BOp_sub, $1, $3) }
|
|
|
|
| expr BO_mul expr { EBinOp (type_exp $1, BOp_mul, $1, $3) }
|
|
|
|
| expr BO_div expr { EBinOp (type_exp $1, BOp_div, $1, $3) }
|
|
|
|
| expr BO_mod expr { EBinOp (type_exp $1, BOp_mod, $1, $3) }
|
|
|
|
| expr BO_and expr { EBinOp (type_exp $1, BOp_and, $1, $3) }
|
|
|
|
| expr BO_or expr { EBinOp (type_exp $1, BOp_or, $1, $3) }
|
|
|
|
| expr BO_arrow expr { EBinOp (type_exp $1, BOp_arrow, $1, $3) }
|
2022-12-09 14:26:28 +01:00
|
|
|
/* Comparison operators */
|
2022-12-09 17:01:04 +01:00
|
|
|
| expr EQUAL expr { EComp (Ast.FTBase Ast.TBool, COp_eq, $1, $3) }
|
|
|
|
| expr CMP_neq expr { EComp (Ast.FTBase Ast.TBool, COp_neq, $1, $3) }
|
|
|
|
| expr CMP_le expr { EComp (Ast.FTBase Ast.TBool, COp_le, $1, $3) }
|
|
|
|
| expr CMP_lt expr { EComp (Ast.FTBase Ast.TBool, COp_lt, $1, $3) }
|
|
|
|
| expr CMP_ge expr { EComp (Ast.FTBase Ast.TBool, COp_ge, $1, $3) }
|
|
|
|
| expr CMP_gt expr { EComp (Ast.FTBase Ast.TBool, COp_gt, $1, $3) }
|
2022-12-09 14:26:28 +01:00
|
|
|
/* Tertiary operators */
|
2022-12-09 17:01:04 +01:00
|
|
|
| IF expr THEN expr ELSE expr { ETriOp (type_exp $4, TOp_if, $2, $4, $6) }
|
|
|
|
| TO_merge expr expr expr { ETriOp (type_exp $4, TOp_merge, $2, $3, $4) }
|
2022-12-09 14:26:28 +01:00
|
|
|
/* When is neither a binop (a * 'a -> 'a) or a comp ('a * 'a -> bool) */
|
2022-12-09 17:01:04 +01:00
|
|
|
| expr WHEN expr { EWhen (type_exp $1, $1, $3) }
|
2022-12-09 14:26:28 +01:00
|
|
|
/* Constants */
|
2022-12-09 17:01:04 +01:00
|
|
|
| CONST_INT { EConst (Ast.FTBase Ast.TInt, CInt $1) }
|
|
|
|
| CONST_BOOL { EConst (Ast.FTBase Ast.TBool, CBool $1) }
|
|
|
|
| CONST_REAL { EConst (Ast.FTBase Ast.TReal, CReal $1) }
|
2022-12-09 14:26:28 +01:00
|
|
|
/* Tuples */
|
|
|
|
| LPAREN expr_comma_list RPAREN { $2 }
|
|
|
|
/* Applications */
|
|
|
|
| IDENT LPAREN expr_comma_list RPAREN
|
|
|
|
{ let name = $1 in
|
2022-12-09 17:01:04 +01:00
|
|
|
let node = fetch_node name in
|
2022-12-09 14:26:28 +01:00
|
|
|
let args = $3 in
|
2022-12-09 17:01:04 +01:00
|
|
|
match node.n_type with
|
|
|
|
| Ast.FTArr (_, t) -> EApp (t, fetch_node name, args)
|
|
|
|
| _ -> raise (MyParsingError "This exception should not have been raised from the dead.")
|
|
|
|
}
|
2022-12-07 21:56:38 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
expr_comma_list:
|
2022-12-09 14:26:28 +01:00
|
|
|
| expr
|
|
|
|
{ let e = $1 in
|
|
|
|
match e with
|
|
|
|
| ETuple _ -> e
|
2022-12-09 17:01:04 +01:00
|
|
|
| _ -> ETuple (Ast.FTList [type_exp e], [e]) }
|
2022-12-09 14:26:28 +01:00
|
|
|
| expr COMMA expr_comma_list
|
|
|
|
{ let e = $1 in
|
|
|
|
let le = $3 in
|
|
|
|
match e, le with
|
2022-12-09 17:01:04 +01:00
|
|
|
| ETuple (Ast.FTList l1, t), ETuple (Ast.FTList l2, t') -> ETuple (Ast.FTList (l1@l2), t @ t')
|
|
|
|
| _, ETuple (Ast.FTList lt, t') -> ETuple (Ast.FTList ((type_exp e)::lt), e :: t')
|
2022-12-09 14:26:28 +01:00
|
|
|
| _, _ -> raise (MyParsingError "This exception should not have been \
|
|
|
|
raised.") }
|
2022-12-07 16:45:55 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
ident_comma_list:
|
|
|
|
| IDENT { [$1] }
|
|
|
|
| IDENT COMMA ident_comma_list { $1 :: $3 }
|
|
|
|
;
|
|
|
|
|