lv6parser.mly 38.97 KiB
%{
open Lxm
open AstPredef
open AstV6
open AstCore
open Lv6parserUtils
(**********************************************************************************)
(**********************************************************************************)
(**********************************************************************************)
(*
TODO:
- reindent
*)
%}
%token TK_EOF
%token <Lxm.t> TK_ERROR
%token <Lxm.t> TK_EXTERN
%token <Lxm.t> TK_UNSAFE
%token <Lxm.t> TK_AND
%token <Lxm.t> TK_ARROW
%token <Lxm.t> TK_ASSERT
%token <Lxm.t> TK_BAR
%token <Lxm.t> TK_BOOL
%token <Lxm.t> TK_CDOTS
%token <Lxm.t> TK_CLOSE_BRACE
%token <Lxm.t> TK_CLOSE_BRACKET
%token <Lxm.t> TK_CLOSE_PAR
%token <Lxm.t> TK_CLOSE_STATIC_PAR
%token <Lxm.t> TK_COLON
%token <Lxm.t> TK_COMA
%token <Lxm.t> TK_CONST
%token <Lxm.t> TK_CURRENT
%token <Lxm.t> TK_DIESE
%token <Lxm.t> TK_DIV
%token <Lxm.t> TK_DOT
%token <Lxm.t> TK_EQ
%token <Lxm.t> TK_ELSE
%token <Lxm.t> TK_ENUM
%token <Lxm.t> TK_FALSE
%token <Lxm.t> TK_FUNCTION
%token <Lxm.t> TK_GT
%token <Lxm.t> TK_GTE
%token <Lxm.t> TK_HAT
%token <Lxm.t> TK_ICONST
%token <Lxm.t> TK_IDENT
%token <Lxm.t> TK_LONGIDENT
%token <Lxm.t> TK_IF
%token <Lxm.t> TK_IMPL
%token <Lxm.t> TK_INT
%token <Lxm.t> TK_LET
%token <Lxm.t> TK_LT
%token <Lxm.t> TK_LTE
%token <Lxm.t> TK_MERGE
%token <Lxm.t> TK_MINUS
%token <Lxm.t> TK_MOD
%token <Lxm.t> TK_NEQ
%token <Lxm.t> TK_NODE
%token <Lxm.t> TK_NOR
%token <Lxm.t> TK_NOT
%token <Lxm.t> TK_OPEN_BRACE
%token <Lxm.t> TK_OPEN_BRACKET
%token <Lxm.t> TK_OPEN_PAR
%token <Lxm.t> TK_OPEN_STATIC_PAR
%token <Lxm.t> TK_OPERATOR
%token <Lxm.t> TK_OR
%token <Lxm.t> TK_PCENT
%token <Lxm.t> TK_PLUS
%token <Lxm.t> TK_POWER
%token <Lxm.t> TK_PRE
%token <Lxm.t> TK_FBY
%token <Lxm.t> TK_RCONST
%token <Lxm.t> TK_REAL
%token <Lxm.t> TK_RETURNS
%token <Lxm.t> TK_SEMICOL
%token <Lxm.t> TK_SLASH
%token <Lxm.t> TK_STAR
%token <Lxm.t> TK_STEP
%token <Lxm.t> TK_STRUCT
%token <Lxm.t> TK_TEL
%token <Lxm.t> TK_THEN
%token <Lxm.t> TK_TRUE
%token <Lxm.t> TK_TYPE
%token <Lxm.t> TK_VAR
%token <Lxm.t> TK_WHEN
%token <Lxm.t> TK_WITH
%token <Lxm.t> TK_XOR
%token <Lxm.t> TK_MODEL
%token <Lxm.t> TK_PACKAGE
%token <Lxm.t> TK_NEEDS
%token <Lxm.t> TK_PROVIDES
%token <Lxm.t> TK_USES
%token <Lxm.t> TK_IS
%token <Lxm.t> TK_BODY
%token <Lxm.t> TK_END
%token <Lxm.t> TK_INCLUDE
%token <Lxm.t> TK_STRING
/* %token <Lxm.t> TK_QUOTE */
/* Priorities */
%left TK_ELSE
%left TK_BAR
%left TK_ARROW
%nonassoc TK_STEP
%nonassoc TK_CDOTS
%right TK_IMPL
%left TK_OR TK_XOR
%left TK_AND
%nonassoc TK_LT TK_LTE TK_EQ TK_GTE TK_GT TK_NEQ
%nonassoc TK_NOT
%left TK_PLUS TK_MINUS
%left TK_STAR TK_SLASH TK_PCENT TK_MOD TK_DIV
%left TK_POWER
%left TK_WHEN
%nonassoc TK_INT TK_REAL
%nonassoc TK_UMINUS TK_PRE TK_CURRENT TK_DIESE TK_NOR /* TK_DIESE TK_NOR useless ? */
%left TK_HAT TK_DOT
%right TK_OPEN_BRACKET TK_OPEN_BRACE TK_SEMICOL
%right TK_COMA
%right TK_FBY
/* Entry point */
%start program
%type <AstV6.t> program
%%
/*-------------------------------------------------------
GRAMMAR
---------------------------------------------------------
NOTES ON THE CODE:
- Nothing is "built" for the main list declarations :
each definition is directly inserted in the corresponding
hash table (i.e. each declaration makes a side effect)
- Any rule that produces a caml list builds it in THE REVERSE
ORDER (in order to save the yacc stack and to avoid
the use of the caml @ operator). This is why they are
named "TotoReverseList". This is why they must not be
used in other rules: onr have to use the corresponding
"TotoList" which finally reverse the list.
-------------------------------------------------------*/
/*
A lustre file is either an old-fashioned list of item decl,
or a list of pack/model declaration
*/
/* ebnf:group=ProgramRules */
program: IncludeList PackBody TK_EOF
{
AstV6.PRPackBody(List.rev $1, $2)
}
| IncludeList PackList TK_EOF
{
AstV6.PRPack_or_models (List.rev $1, List.rev $2)
}
;
/* ebnf:group=PackageRules */
PackList: OnePack
{ [$1] }
| PackList OnePack
{ $2::$1 }
;
OnePack: /* ebnf:print=short */
ModelDecl
{ AstV6.NSModel $1 }
| PackDecl
{ AstV6.NSPack $1 }
| PackEq
{ AstV6.NSPack $1 }
;
/* ebnf:group=ProgramRules */
Include: TK_INCLUDE TK_STRING
{ (Lxm.str $2) }
;
IncludeList: /* ebnf:print=expand */
/* empty */
{ [] }
| IncludeList Include
{ $2::$1 }
;
/*
Pour les provides, on rend des decls, bien
que syntaxiquement, on n'autorise pas n'importe quoi ...
*/
/* ebnf:group=ModelRules */
Provides:
/* nada */
{ None }
/* | TK_PROVIDES StaticParamList TK_SEMICOL */
| TK_PROVIDES ProvideList
{ Some (List.rev $2) }
;
ProvideList: /* ebnf:print=expand */ Provide TK_SEMICOL
{ [$1] }
| ProvideList Provide TK_SEMICOL
{ $2::$1 }
;
Provide:
/* constante abstraite */
TK_CONST Lv6Id TK_COLON Type ConstDefOpt
{
Lxm.flagit
(ConstInfo (ExternalConst (Lxm.id $2, $4, $5)))
$2
}
/* noeud abstrait
2015/07 -> les noeuds/fonctions parametriques n'taient pas prvus
manque : StaticParams
voir : Lv6parserUtils.treat_abstract_node
*/
| TK_UNSAFE TK_NODE Lv6Id StaticParams Params TK_RETURNS Params
{
treat_abstract_node true true $3 $4 $5 $7
}
/* fonction abstraite */
| TK_NODE Lv6Id StaticParams Params TK_RETURNS Params
{
treat_abstract_node false true $2 $3 $4 $6
}
/* fonction abstraite */
| TK_UNSAFE TK_FUNCTION Lv6Id StaticParams Params TK_RETURNS Params
{
treat_abstract_node true false $3 $4 $5 $7
}
| TK_FUNCTION Lv6Id StaticParams Params TK_RETURNS Params
{
treat_abstract_node false false $2 $3 $4 $6
}
/* type abstrait... */
| TK_TYPE OneTypeDecl
{ Lxm.flagit (TypeInfo (snd $2)) (fst $2) }
;
/* ebnf:group=ConstRules */
ConstDefOpt: /* ebnf:print=expand */
{ None}
| TK_EQ Expression
{
Some $2
}
;
/* ebnf:group=ModelRules */
ModelDecl:
TK_MODEL Lv6Id
Uses
/* TK_NEEDS PackParamList TK_SEMICOL */
TK_NEEDS StaticParamList TK_SEMICOL
Provides
TK_BODY
PackBody
TK_END
{
let mdecl = {
mo_name = (Lv6Id.pack_name_of_string (Lxm.str $2));
mo_uses = $3 ;
mo_needs = (List.rev $5) ;
mo_provides = $7 ;
mo_body = $9;
} in
{it = mdecl; src = $2 }
}
;
/* ebnf:group=PackageRules */
PackDecl:
TK_PACKAGE Lv6Id
Uses
Provides
TK_BODY
PackBody
TK_END
{
let pdef = PackGiven {
pg_uses = $3 ;
pg_provides = $4 ;
pg_body = $6;
} in
let pdecl = {
pa_name = (Lv6Id.pack_name_of_string (Lxm.str $2));
pa_def = pdef;
} in
{it = pdecl; src = $2 }
}
;
/* pack params are identical to node static Packparams (?) */
/*
PackParamList:
StaticParamList
{ $1 }
;
*/
Uses:
/* nada */
{ [] }
| TK_USES Lv6IdList TK_SEMICOL
{
List.rev_map lexeme_to_pack_name_flagged $2
}
;
/* */
Eq_or_Is: TK_EQ {}
| TK_IS {}
;
/* I don't like by-pos notation, but keep it
for backward compatibility
*/
PackEq:
TK_PACKAGE Lv6Id Eq_or_Is Lv6Id TK_OPEN_PAR
ByNameStaticArgList
TK_CLOSE_PAR TK_SEMICOL
{
let pdef = PackInstance {
pi_model = (Lxm.id $4);
pi_args = (List.rev $6);
} in
let pa = {
pa_name = (Lv6Id.pack_name_of_string (Lxm.str $2));
pa_def = pdef;
} in
{it = pa; src = $2 }
}
;
/* ebnf:group=ProgramRules */
/* PackBody :
les informations collectes dans les tables
sont figes, et on remet les tables 0 ...
*/
PackBody:
DeclList
{
let res = AstV6.make_packbody
const_table type_table node_table (List.rev !def_list) in
(* clean all ... *)
Hashtbl.clear const_table ;
Hashtbl.clear type_table ;
Hashtbl.clear node_table ;
def_list := [] ;
res
}
;
/* Declarations */
DeclList: /* ebnf:print=expand */
OneDecl
{ }
| DeclList OneDecl
{ }
;
OneDecl: /* ebnf:print=short */
ConstDecl
{ }
| TypeDecl
{ }
| ExtNodeDecl
{ }
| NodeDecl
{ }
;
/* Lv6Idifiers and lists */
/* ebnf:group=IdentVIRules */
Lv6IdRef: /* ebnf print=ignore */
/* simple or long ... */
TK_IDENT
{ idref_of_lxm $1 }
| TK_LONGIDENT
{ idref_of_lxm $1 }
;
/* Lv6Idifiers and lists */
/* ebnf:group=IdentRules */
Lv6Id: /* ebnf print=ignore */
TK_IDENT Pragma
{ (Lv6parserUtils.make_ident $1 $2) }
;
Lv6IdList: /* ebnf:print=expand */
Lv6Id
{ [$1] }
| Lv6IdList TK_COMA Lv6Id
{ $3::$1 }
;
/* ebnf:group=NodesRules */
TypedLv6IdsList: TypedLv6Ids
{ [ $1 ] }
| TypedLv6IdsList TK_SEMICOL TypedLv6Ids
{ $3::$1 }
;
TypedLv6Ids: Lv6IdList TK_COLON Type
/* WARNING ! il faut remettre la liste l'endroit */
{ ((List.rev $1), $3 ) }
;
TypedValuedLv6Ids: TypedValuedLv6Id
{ $1 }
| TypedValuedLv6Ids TK_SEMICOL TypedValuedLv6Id
{ List.append $1 $3 }
;
TypedValuedLv6Id :
/* Les listes d'idents en partie gauche sont
acceptes pour les idents SANS valeur
*/
Lv6Id TK_COLON Type
{ (id_valopt_list_of_id_list [$1] $3 ) }
| Lv6Id TK_COMA Lv6IdList TK_COLON Type
{ (id_valopt_list_of_id_list ($1::(List.rev $3)) $5) }
/* Mais pas pour les constantes dfinies :
*/
| Lv6Id TK_COLON Type TK_EQ Expression
{ [id_valopt_of_id_val $1 $3 $5] }
;
/* constantes */
/* ebnf:group=ConstantDeclRules */
ConstDecl: TK_CONST ConstDeclList
{ treat_const_decl_list $2 }
;
ConstDeclList:
OneConstDecl TK_SEMICOL
{ $1 }
| ConstDeclList OneConstDecl TK_SEMICOL
{ $1 @ $2 }
;
/* Retourne une liste (lxm, const_info) */
OneConstDecl:
/* Les listes d'idents en partie gauche sont acceptes
pour les constantes externes : */
Lv6Id TK_COLON Type
{ (make_external_const_list [$1] $3 ) }
| Lv6Id TK_COMA Lv6IdList TK_COLON Type
{ (make_external_const_list ($1::(List.rev $3)) $5) }
/* Mais pas pour les constantes dfinies : */
| Lv6Id TK_COLON Type TK_EQ Expression
{ [ (make_defined_const $1 (Some $3) $5) ] }
| Lv6Id TK_EQ Expression
{ [ (make_defined_const $1 (None) $3 ) ] }
;
/* types */
/* ebnf:group=TypeDeclRules */
TypeDecl: TK_TYPE TypeDeclList
{ List.iter treat_type_decl (List.rev $2) }
;
TypeDeclList: OneTypeDecl TK_SEMICOL
{ [$1] }
| TypeDeclList OneTypeDecl TK_SEMICOL
{ $2::$1 }
;
/* returns a couple (lxm, type_info) */
OneTypeDecl:
/* type abstrait (externes) */
Lv6Id
{ ($1, ExternalType (Lxm.id $1)) }
/* un alias sur type immdiat */
| Lv6Id TK_EQ Type
{ ($1, AliasedType ((Lxm.id $1), $3)) }
/* type numr */
/* WARNING ! il faut remettre la liste l'endroit */
| Lv6Id TK_EQ TK_ENUM TK_OPEN_BRACE Lv6IdList TK_CLOSE_BRACE
{
let cstnamelist = List.rev_map lexeme_to_ident_flagged $5 in
($1, EnumType ((Lxm.id $1), cstnamelist))
}
/* type structure champs nomms */
/* WARNING ! la liste est dj l'endroit */
| Lv6Id TK_EQ OptStruct TK_OPEN_BRACE TypedValuedLv6Ids OptSemicol TK_CLOSE_BRACE
{
let typinfo = StructType (make_struct_type_info $1 $5) in
($1, typinfo)
}
;
/* COMPATIBILITY : "struct" keyword is optional */
OptStruct: /* ebnf:print=expand */
/* nothing */ {}
| TK_STRUCT {}
;
/* ebnf:group=SimpleTypeRules */
/* Notation de type "immdiat" */
Type:
/* prdfini */
TK_BOOL { {src=$1; it=Bool_type_exp } }
| TK_INT { {src=$1; it=Int_type_exp } }
| TK_REAL { {src=$1; it=Real_type_exp } }
/* ref un type nomm */
| Lv6IdRef { {src=$1.src; it= Named_type_exp $1.it } }
/* ou tableau immdiat */
| Type TK_HAT Expression
{ {src=$2; it=Array_type_exp ($1 , $3) } }
;
/* extern nodes */
/* ebnf:group=ExtNodesRules */
ExtNodeDecl:
TK_EXTERN TK_FUNCTION Lv6Id Params TK_RETURNS Params OptSemicol
{ treat_external_node false false $3 $4 $6 }
| TK_UNSAFE TK_EXTERN TK_FUNCTION Lv6Id Params TK_RETURNS Params OptSemicol
{ treat_external_node true false $4 $5 $7 }
| TK_EXTERN TK_NODE Lv6Id Params TK_RETURNS Params OptSemicol
{ treat_external_node false true $3 $4 $6 }
| TK_UNSAFE TK_EXTERN TK_NODE Lv6Id Params TK_RETURNS Params OptSemicol
{ treat_external_node true true $4 $5 $7 }
;
/* noeuds */
/* ebnf:group=NodesRules */
NodeDecl: LocalNode {};
LocalNode:
TK_NODE Lv6Id StaticParams Params TK_RETURNS Params OptSemicol
LocalDecls Body OptEndNode
{ treat_node_decl false true $2 $3 $4 $6 $8 (fst $9) (snd $9) }
| TK_FUNCTION Lv6Id StaticParams Params TK_RETURNS Params OptSemicol
LocalDecls Body OptEndNode
{ treat_node_decl false false $2 $3 $4 $6 $8 (fst $9) (snd $9) }
| TK_NODE Lv6Id StaticParams NodeProfileOpt TK_EQ EffectiveNode OptSemicol
{ treat_node_alias false true $2 $3 $4 $6 }
| TK_FUNCTION Lv6Id StaticParams NodeProfileOpt TK_EQ EffectiveNode OptSemicol
{ treat_node_alias false false $2 $3 $4 $6 }
| TK_UNSAFE TK_NODE Lv6Id StaticParams Params TK_RETURNS Params OptSemicol
LocalDecls Body OptEndNode
{ treat_node_decl true true $3 $4 $5 $7 $9 (fst $10) (snd $10) }
| TK_UNSAFE TK_FUNCTION Lv6Id StaticParams Params TK_RETURNS Params OptSemicol
LocalDecls Body OptEndNode
{ treat_node_decl true false $3 $4 $5 $7 $9 (fst $10) (snd $10) }
| TK_UNSAFE TK_NODE Lv6Id StaticParams NodeProfileOpt TK_EQ EffectiveNode OptSemicol
{ treat_node_alias true true $3 $4 $5 $7 }
| TK_UNSAFE TK_FUNCTION Lv6Id StaticParams NodeProfileOpt TK_EQ EffectiveNode OptSemicol
{ treat_node_alias true false $3 $4 $5 $7 }
;
NodeProfileOpt :
/* nada */
{ None }
| Params TK_RETURNS Params
{
let invars = clocked_ids_to_var_infos VarInput $1 in
let outvars = clocked_ids_to_var_infos VarOutput $3 in
Some (invars, outvars)
}
;
/* ebnf:group=StaticRules */
StaticParams: /*rien*/
{ [] }
| TK_OPEN_STATIC_PAR StaticParamList TK_CLOSE_STATIC_PAR
{ (List.rev $2) }
;
StaticParamList:
StaticParam
{ [$1] }
| StaticParamList TK_SEMICOL StaticParam
{ $3::$1 }
;
StaticParam:
TK_TYPE Lv6Id
{ {it=(StaticParamType (Lxm.id $2)); src=$2} }
| TK_CONST Lv6Id TK_COLON Type
{ {it=(StaticParamConst (Lxm.id $2 , $4)); src=$2} }
| TK_NODE Lv6Id Params TK_RETURNS Params
{
let invars = clocked_ids_to_var_infos VarInput $3 in
let outvars = clocked_ids_to_var_infos VarOutput $5 in
let xn = StaticParamNode (
Lxm.id $2,
invars,
outvars,
true,
true
) in
Lxm.flagit xn $2
}
| TK_FUNCTION Lv6Id Params TK_RETURNS Params
{
let invars = clocked_ids_to_var_infos VarInput $3 in
let outvars = clocked_ids_to_var_infos VarOutput $5 in
let xn = StaticParamNode (
Lxm.id $2,
invars,
outvars,
false,
true
) in
Lxm.flagit xn $2
}
| TK_UNSAFE TK_NODE Lv6Id Params TK_RETURNS Params
{
let invars = clocked_ids_to_var_infos VarInput $4 in
let outvars = clocked_ids_to_var_infos VarOutput $6 in
let xn = StaticParamNode (
Lxm.id $3,
invars,
outvars,
true,
false
) in
Lxm.flagit xn $3
}
| TK_UNSAFE TK_FUNCTION Lv6Id Params TK_RETURNS Params
{
let invars = clocked_ids_to_var_infos VarInput $4 in
let outvars = clocked_ids_to_var_infos VarOutput $6 in
let xn = StaticParamNode (
Lxm.id $3,
invars,
outvars,
false,
false
) in
Lxm.flagit xn $3
}
;
/* Le "." la fin des noeuds est une fioriture historique,
On accepte donc '.' ';' ou rien du tout !
*/
OptEndNode: /* ebnf:print=expand */
TK_DOT
{}
| OptSemicol
{}
;
/* Aucune difference entre params d'entre et les autres */
/* params de sortie :
type: sx_Param list = (((Lxm.t list) * type_exp) list * AstCore.clock_exp) list
*/
/* ebnf:group=NodesRules */
Params:
/* rien */
TK_OPEN_PAR TK_CLOSE_PAR
{ [] }
|
TK_OPEN_PAR VarDeclList OptSemicol TK_CLOSE_PAR
/* WARNING ! il faut remettre la liste l'endroit */
{ (List.rev $2) }
;
/* Dclarations locales(2010/07/02)
concret: liste de var(s) ou const
abstrait: couple liste de vars * list de consts
*/
LocalDecls:
/* nada */
{ ([],[]) }
| LocalDeclList
{ $1 }
;
LocalDeclList:
OneLocalDecl
{ $1 }
| LocalDeclList OneLocalDecl
{
match ($1,$2) with
| ( (vl1, cl1) , (vl2, cl2)) ->
( vl2 @ vl1, cl2 @ cl1)
}
;
OneLocalDecl:
LocalVars
{ ($1, []) }
| LocalConsts
{ ([], $1) }
;
/* Dclaration de constantes locale (2010/07/02)
uniquement des constantes dfinies
*/
LocalConsts:
TK_CONST ConstDeclList
{ $2 }
;
/* variables locales */
LocalVars:
TK_VAR VarDeclList TK_SEMICOL
/* WARNING ! il faut remettre la liste l'endroit */
{ (List.rev $2) }
;
/* liste de dclarations de vars types et clockes */
VarDeclList: VarDecl
{ [$1] }
| VarDeclList TK_SEMICOL VarDecl
{ $3::$1 }
;
/* dclaration de vars ventuellement clockes */
VarDecl:
/*
Pas de clock : sous-entendu sur la base
exemple: x, ..., z : type
*/
TypedLv6Ids
{ ([$1], Base) }
|
/*
Clock explicite sur UNE seule liste d'idents typs
exemple: x, ..., z : type when clock
*/
TypedLv6Ids TK_WHEN ClockExpr
{ ([$1], $3) }
|
/*
Clock explicite sur PLUSIEURS listes d'idents typs
exemple: (x,..,z : t1 ; a,...,b : t2) when clock
*/
TK_OPEN_PAR TypedLv6IdsList TK_CLOSE_PAR TK_WHEN ClockExpr
/* WARNING ! il faut remettre la liste l'endroit */
{ ( (List.rev $2), $5 ) }
;
/* Corps d'un noeud */
/*
Retourne un couple (assertions list, equations list)
*/
/* ebnf:group=BodyRules */
Body:
TK_LET TK_TEL
{ ([], []) }
| TK_LET EquationList TK_TEL
/* WARNING ! il faut remettre les listes l'endroit */
{ (List.rev (fst $2) , List.rev (snd $2)) }
;
/* Equations */
EquationList: Equation
{ $1 }
| EquationList Equation
{ ( (fst $2) @ (fst $1) , (snd $2) @ (snd $1) ) }
;
Equation: TK_ASSERT Expression TK_SEMICOL
{ ( [ {src = $1; it = $2} ] , [] ) }
| Left TK_EQ Expression TK_SEMICOL
{ ( [] , [ {src = $2; it = ($1, $3) } ] ) }
;
/* partie gauche d'equation */
/* ebnf:group=LeftRules */
Left: LeftItemList
/* WARNING ! il faut remettre la liste l'endroit */
{ (List.rev $1) }
| TK_OPEN_PAR LeftItemList TK_CLOSE_PAR
/* WARNING ! il faut remettre la liste l'endroit */
{ (List.rev $2) }
;
LeftItemList: LeftItem
{ [$1] }
| LeftItemList TK_COMA LeftItem
{ $3::$1 }
;
LeftItem: Lv6Id
{ LeftVar ( {src = $1; it = Lxm.id $1} ) }
| FieldLeftItem
{ $1 }
| TableLeftItem
{ $1 }
;
FieldLeftItem: LeftItem TK_DOT Lv6Id
{ LeftField ($1 , {src = $3; it = Lxm.id $3} ) }
;
TableLeftItem:
LeftItem TK_OPEN_BRACKET Expression TK_CLOSE_BRACKET
{ LeftArray ($1 , {src = $2; it = $3}) }
| LeftItem TK_OPEN_BRACKET Select TK_CLOSE_BRACKET
{ LeftSlice ($1, $3 ) }
;
/* partie droite d'equation (expression) */
/* ebnf:group=ExpressionRules */
Expression:
/* zroaires */
Constant { $1 }
| Lv6IdRef { leafexp $1.src (IDENT_n $1.it) }
/* unaires */
| TK_NOT Expression { unexp_predef $1 NOT_n $2 }
| TK_MINUS Expression %prec TK_UMINUS
{ unexp_predef $1 UMINUS_n $2 }
| TK_PRE Expression { unexp $1 PRE_n $2 }
| TK_CURRENT Expression { unexp $1 CURRENT_n $2 }
| TK_INT Expression { unexp_predef $1 REAL2INT_n $2 }
| TK_REAL Expression { unexp_predef $1 INT2REAL_n $2 }
/* binaires */
| Expression TK_WHEN ClockExpr
{ unexp $2 (WHEN_n $3) $1 }
| Expression TK_FBY Expression { binexp $2 FBY_n $1 $3 }
| Expression TK_ARROW Expression { binexp $2 ARROW_n $1 $3 }
| Expression TK_AND Expression { binexp_predef $2 AND_n $1 $3 }
| Expression TK_OR Expression { binexp_predef $2 OR_n $1 $3 }
| Expression TK_XOR Expression { binexp_predef $2 XOR_n $1 $3 }
| Expression TK_IMPL Expression { binexp_predef $2 IMPL_n $1 $3 }
| Expression TK_EQ Expression { binexp_predef $2 EQ_n $1 $3 }
| Expression TK_NEQ Expression { binexp_predef $2 NEQ_n $1 $3 }
| Expression TK_LT Expression { binexp_predef $2 LT_n $1 $3 }
| Expression TK_LTE Expression { binexp_predef $2 LTE_n $1 $3 }
| Expression TK_GT Expression { binexp_predef $2 GT_n $1 $3 }
| Expression TK_GTE Expression { binexp_predef $2 GTE_n $1 $3 }
| Expression TK_DIV Expression { binexp_predef $2 DIV_n $1 $3 }
| Expression TK_MOD Expression { binexp_predef $2 MOD_n $1 $3 }
| Expression TK_MINUS Expression { binexp_predef $2 MINUS_n $1 $3 }
| Expression TK_PLUS Expression { binexp_predef $2 PLUS_n $1 $3 }
| Expression TK_SLASH Expression { binexp_predef $2 SLASH_n $1 $3 }
| Expression TK_STAR Expression { binexp_predef $2 TIMES_n $1 $3 }
/* ternaires */
| TK_IF Expression TK_THEN Expression TK_ELSE Expression
{ ternexp_predef $1 IF_n $2 $4 $6 }
| TK_WITH Expression TK_THEN Expression TK_ELSE Expression
{ CallByPos( {src = $1 ; it = WITH_n($2, $4, $6) }, Oper [] ) }
/* n-aires */
/* WARNING ! il faut remettre la liste l'endroit */
| TK_DIESE TK_OPEN_PAR ExpressionList TK_CLOSE_PAR
{ naryexp_predef $1 DIESE_n (List.rev $3) }
| TK_NOR TK_OPEN_PAR ExpressionList TK_CLOSE_PAR
{ naryexp_predef $1 NOR_n (List.rev $3) }
| CallByPosExpression
{ $1 }
/* Oprations sur les tableaux */
/* -> cration partir d'une liste */
| TK_OPEN_BRACKET ExpressionList TK_CLOSE_BRACKET
{ naryexp $1 ARRAY_n (List.rev $2) }
/* -> cration par exponentiation */
| Expression TK_HAT Expression { binexp $2 HAT_n $1 $3 }
/* -> concatnation */
| Expression TK_BAR Expression { binexp $2 CONCAT_n $1 $3 }
/* -> accs un lment */
| Expression TK_OPEN_BRACKET Expression TK_CLOSE_BRACKET
{ unexp $2 (ARRAY_ACCES_n $3) $1 }
/* -> accs une tranche */
| Expression TK_OPEN_BRACKET Select TK_CLOSE_BRACKET
{ unexp $3.src (ARRAY_SLICE_n $3.it) $1 }
/* Acces aux structures */
| Expression TK_DOT Lv6Id
{ unexp $2 (STRUCT_ACCESS_n (Lxm.id $3)) $1 }
/* Appels par noms */
| CallByNameExpression
{ $1 }
/* Parenthesis or tuple */
| TK_OPEN_PAR ExpressionList TK_CLOSE_PAR
{ if (List.length $2 = 1) then (List.hd $2) else naryexp $1 TUPLE_n (List.rev $2) }
/* merge */
| TK_MERGE Lv6Id MergeCaseList
{ make_merge_op $2 $3 }
;
/* WARNING ! : les listes sont cres l'envers */
ExpressionList:
/* empty */
{ [] }
| Expression
{ [$1] }
| ExpressionList TK_COMA Expression
{ $3::$1 }
;
/* ebnf:group=MergeRules */
MergeCaseList:
| MergeCase
{ [$1] }
| MergeCaseList MergeCase
{ $2::$1 }
;
MergeCase:
| TK_OPEN_PAR Lv6IdRef TK_ARROW Expression TK_CLOSE_PAR
{ (Idref $2.it,$2.src,$4) }
| TK_OPEN_PAR TK_TRUE TK_ARROW Expression TK_CLOSE_PAR
{ (Bool true, $2,$4) }
| TK_OPEN_PAR TK_FALSE TK_ARROW Expression TK_CLOSE_PAR
{ (Bool false, $2,$4) }
;
/* ebnf:group=ExpressionRules */
ClockExpr:
Lv6IdRef TK_OPEN_PAR Lv6Id TK_CLOSE_PAR
{ (make_clock_exp $1.it $3) }
| Lv6Id { (make_clock_exp (Lv6Id.idref_of_string "Lustre::true") $1) }
| TK_NOT Lv6Id { (make_clock_exp (Lv6Id.idref_of_string "Lustre::false") $2) }
| TK_NOT TK_OPEN_PAR Lv6Id TK_CLOSE_PAR
{ (make_clock_exp (Lv6Id.idref_of_string "Lustre::false") $3) }
;
/* ebnf:group=PredefRules */
PredefOp: /* ebnf:print=short */
TK_NOT { make_predef_posop $1 NOT_n }
| TK_FBY { {src=$1; it=FBY_n} }
| TK_PRE { {src=$1; it=PRE_n} }
| TK_CURRENT{ {src=$1; it=CURRENT_n} }
| TK_ARROW { {src=$1; it=ARROW_n} }
| TK_AND { make_predef_posop $1 AND_n }
| TK_OR { make_predef_posop $1 OR_n }
| TK_XOR { make_predef_posop $1 XOR_n }
| TK_IMPL { make_predef_posop $1 IMPL_n }
| TK_EQ { make_predef_posop $1 EQ_n }
| TK_NEQ { make_predef_posop $1 NEQ_n }
| TK_LT { make_predef_posop $1 LT_n }
| TK_LTE { make_predef_posop $1 LTE_n }
| TK_GT { make_predef_posop $1 GT_n }
| TK_GTE { make_predef_posop $1 GTE_n }
| TK_DIV { make_predef_posop $1 DIV_n }
| TK_MOD { make_predef_posop $1 MOD_n }
| TK_MINUS { make_predef_posop $1 MINUS_n }
| TK_PLUS { make_predef_posop $1 PLUS_n }
| TK_SLASH { make_predef_posop $1 SLASH_n }
| TK_STAR { make_predef_posop $1 TIMES_n }
| TK_IF { make_predef_posop $1 IF_n }
;
/* nothing to do here !!!
| TK_WHEN ClockExpr { {src=$1; it=(WHEN_n $2)} }
| TK_WHEN { {src=$1; it=(WHEN_n Base)} }
*/
/* Appel fonctionnel par position (classique) */
/* NB
On a 2 rgles cause des appels chantillonns
*/
/* ebnf:group=ExpressionRules */
CallByPosExpression:
/*
EffectiveNode TK_OPEN_PAR Expression TK_CLOSE_PAR
{ naryexp $1.src (CALL_n $1) [$3] }
|
*/
EffectiveNode TK_OPEN_PAR ExpressionList TK_CLOSE_PAR
{ naryexp $1.src (CALL_n $1) (List.rev $3) }
;
/* Effective node : une constrcution qui designe un noeud */
/* ebnf:group=StaticRules */
EffectiveNode:
/* Juste un nom */
Lv6IdRef
{ {src=$1.src; it=(($1.it, [])) } }
/* Un nom + des params statiques */
| Lv6IdRef TK_OPEN_STATIC_PAR StaticArgList TK_CLOSE_STATIC_PAR
{ {src=$1.src; it=(($1.it, List.rev $3)) } }
/* Un operateur prdfini
| TK_OPERATOR PredefOp,[]
{ {src=$; it=($2.it, []) } }
XXX pour l'instant, j'enleve la possibilit d'avoir
(operator +(1,2)). On verra ca plus tard
*/
;
StaticArgList:
StaticArg
{ [$1] }
| StaticArgList TK_COMA StaticArg
{ $3::$1 }
/* let's be permissive... */
| StaticArgList TK_SEMICOL StaticArg
{ $3::$1 }
;
/* Faut se tordre l'esprit ici !
- la nature est explicite,
- la nature est immediate (type, const ou node predefini)
- la nature est sans ambiguite const (expressions simples)
- la nature est compile-time (juste un ident, a rsoudre)
*/
StaticArg:
/* nature explicite */
TK_TYPE Type
{ {src=$1 ; it=StaticArgType $2 } }
| TK_CONST Expression
{ {src=$1 ; it=StaticArgConst $2 } }
| TK_NODE EffectiveNode
{ {src=$1 ; it=StaticArgNode (CALL_n $2) } }
| TK_FUNCTION EffectiveNode
{ {src=$1 ; it=StaticArgNode (CALL_n $2) } }
| PredefOp
{ {src=$1.src; it=StaticArgNode $1.it } }
/* un ident OU une expression simple ( rsoudre) */
/* c'est au retour qu'on choisit */
| SimpleExp
{
match $1 with
| CallByPos (op, _x) -> (
match op.it with
| IDENT_n idref -> {src=op.src ; it = StaticArgLv6Id idref }
| _ -> {src=op.src ; it= StaticArgConst $1}
)
| Merge_bool_n _
| Merge_n _
| CallByName _ ->
print_string "*** unexpected static argument\n";
assert false
}
/* un type sans ambiguite */
| SurelyType
{ {src=$1.src; it=StaticArgType $1} }
/* un node sans ambiguite */
| SurelyNode
{ {src=$1.src; it=StaticArgNode (CALL_n $1)} }
;
/* for model arguments (copy-pasted from call by position StaticArg */
ByNameStaticArgList:
ByNameStaticArg
{ [$1] }
| ByNameStaticArgList TK_COMA ByNameStaticArg
{ $3::$1 }
/* let's be permissive... */
| ByNameStaticArgList TK_SEMICOL ByNameStaticArg
{ $3::$1 }
;
/* Faut se tordre l'esprit ici !
- la nature est explicite,
- la nature est immediate (type, const ou node predefini)
- la nature est sans ambiguite const (expressions simples)
- la nature est compile-time (juste un ident, a rsoudre)
*/
ByNameStaticArg:
/* nature explicite */
TK_TYPE Lv6Id TK_EQ Type
{ (Lxm.id $2, {src=$1 ; it= StaticArgType $4 }) }
| TK_CONST Lv6Id TK_EQ Expression
{ (Lxm.id $2, {src=$1 ; it= StaticArgConst $4 }) }
| TK_NODE Lv6Id TK_EQ EffectiveNode
{ (Lxm.id $2, {src=$1 ; it= StaticArgNode (CALL_n $4) }) }
| TK_FUNCTION Lv6Id TK_EQ EffectiveNode
{ (Lxm.id $2, {src=$1 ; it= StaticArgNode (CALL_n $4) }) }
| Lv6Id TK_EQ PredefOp
{ Lxm.id $1, {src=$3.src; it=StaticArgNode $3.it } }
/* un ident OU une expression simple ( rsoudre) */
/* c'est au retour qu'on choisit */
| Lv6Id TK_EQ SimpleExp
{ Lxm.id $1,
match $3 with
| CallByPos (op, _x) -> (
match op.it with
| IDENT_n idref -> {src=op.src ; it = StaticArgLv6Id idref }
| _ -> {src=op.src ; it= StaticArgConst $3}
)
| Merge_bool_n _
| Merge_n _
| CallByName _ ->
print_string "*** unexpected static argument\n";
assert false
}
/* un type sans ambiguite */
| Lv6Id TK_EQ SurelyType
{ Lxm.id $1, {src=$3.src; it=StaticArgType $3} }
/* un node sans ambiguite */
| Lv6Id TK_EQ SurelyNode
{ Lxm.id $1, {src=$3.src; it=StaticArgNode (CALL_n $3)} }
;
SurelyNode: Lv6IdRef TK_OPEN_STATIC_PAR StaticArgList TK_CLOSE_STATIC_PAR
{ {src=$1.src; it=($1.it, List.rev $3) } }
;
SurelyType:
/* prdfini */
TK_BOOL { {src=$1; it=Bool_type_exp} }
| TK_INT { {src=$1; it=Int_type_exp} }
| TK_REAL { {src=$1; it=Real_type_exp} }
/* ou tableau immdiat */
| SurelyType TK_HAT Expression
{ {src=$1.src; it = Array_type_exp ($1 , $3) } }
;
/* SimpleExp = (hopefuly) statically evaluable exp */
SimpleExp:
Constant { $1 }
| Lv6IdRef { leafexp $1.src (IDENT_n $1.it) }
| SimpleTuple { $1 }
| TK_NOT SimpleExp { unexp_predef $1 NOT_n $2 }
| TK_MINUS SimpleExp %prec TK_UMINUS { unexp_predef $1 UMINUS_n $2 }
| SimpleExp TK_AND SimpleExp { binexp_predef $2 AND_n $1 $3 }
| SimpleExp TK_OR SimpleExp { binexp_predef $2 OR_n $1 $3 }
| SimpleExp TK_XOR SimpleExp { binexp_predef $2 XOR_n $1 $3 }
| SimpleExp TK_IMPL SimpleExp { binexp_predef $2 IMPL_n $1 $3 }
| SimpleExp TK_EQ SimpleExp { binexp_predef $2 EQ_n $1 $3 }
| SimpleExp TK_NEQ SimpleExp { binexp_predef $2 NEQ_n $1 $3 }
| SimpleExp TK_LT SimpleExp { binexp_predef $2 LT_n $1 $3 }
| SimpleExp TK_LTE SimpleExp { binexp_predef $2 LTE_n $1 $3 }
| SimpleExp TK_GT SimpleExp { binexp_predef $2 GT_n $1 $3 }
| SimpleExp TK_GTE SimpleExp { binexp_predef $2 GTE_n $1 $3 }
| SimpleExp TK_DIV SimpleExp { binexp_predef $2 DIV_n $1 $3 }
| SimpleExp TK_MOD SimpleExp { binexp_predef $2 MOD_n $1 $3 }
| SimpleExp TK_MINUS SimpleExp { binexp_predef $2 MINUS_n $1 $3 }
| SimpleExp TK_PLUS SimpleExp { binexp_predef $2 PLUS_n $1 $3 }
| SimpleExp TK_SLASH SimpleExp { binexp_predef $2 SLASH_n $1 $3 }
| SimpleExp TK_STAR SimpleExp { binexp_predef $2 TIMES_n $1 $3 }
/* ternaires */
| TK_IF SimpleExp TK_THEN SimpleExp TK_ELSE SimpleExp
{ ternexp_predef $1 IF_n $2 $4 $6 }
;
SimpleTuple:
| TK_OPEN_PAR SimpleExpList TK_CLOSE_PAR
{
(match $2 with
| [x] -> x
| l -> naryexp $1 TUPLE_n (List.rev l) )
}
;
SimpleExpList: SimpleExp
{ [$1] }
| SimpleExpList TK_COMA SimpleExp
{ $3::$1 }
;
/* Appel fonctionnel par nom */
/* NB
Actuellement, uniquement pour les structures,
donc pas de soucis d'chantillonnage
*/
/* ebnf:group=ExpressionByNamesRules */
CallByNameExpression:
/* WARNING ! il faut remettre la liste l'endroit */
| Lv6IdRef TK_OPEN_BRACE CallByNameParamList OptSemicol TK_CLOSE_BRACE
{ bynameexp $1.src (STRUCT_n $1.it) (List.rev $3) }
| Lv6IdRef TK_OPEN_BRACE Lv6IdRef TK_WITH CallByNameParamList OptSemicol TK_CLOSE_BRACE
{ bynameexp $1.src (STRUCT_WITH_n ($1.it,$3.it)) (List.rev $5) }
/* on peut avoir une liste vide */
| Lv6IdRef TK_OPEN_BRACE TK_CLOSE_BRACE
{ bynameexp $1.src (STRUCT_n $1.it) ([]) }
/* COMPATIBILITY : immediate "struct" without the type name
| TK_OPEN_BRACE CallByNameParamList OptSemicol TK_CLOSE_BRACE
{ bynameexp $1 STRUCT_anonymous_n (List.rev $2) } */
;
CallByNameParamList:
CallByNameParam
{ [$1] }
|
CallByNameParamList sepVariant CallByNameParam
{ $3::$1 }
;
/* COMPATIBILITY : ',' or ';' */
sepVariant: /* ebnf:print=expand */
TK_SEMICOL
{}
| TK_COMA
{ Lv6errors.warning $1 "separator mismatch, ';' expected"}
;
CallByNameParam:
Lv6Id TK_EQ Expression
{ ({it=Lxm.id $1;src=$1} , $3) }
;
/* ebnf:group=ConstantRules */
Constant: /* ebnf:print=short */
TK_TRUE
{ (leafexp_predef $1 TRUE_n) }
| TK_FALSE
{ (leafexp_predef $1 FALSE_n) }
| IntConst
{ (leafexp_predef $1 (ICONST_n (Lxm.id $1))) }
| RealConst
{ (leafexp_predef $1 ((RCONST_n (Lxm.id $1)))) }
;
IntConst: /* ebnf:print=ignore */
TK_ICONST
{ $1 }
;
RealConst: /* ebnf:print=ignore */
TK_RCONST
{ $1 }
;
/* ebnf:group=LeftRules */
Select:
Expression TK_CDOTS Expression Step
{ {it={si_first = $1; si_last = $3 ; si_step = $4 }; src = $2} }
;
Step: /* empty */
{ None }
| TK_STEP Expression
{ Some $2 }
;
/* NB
AstV6 laxiste des listes :
quand il n'y a pas d'ambiguit,
les ";" sont vus indifferemment commme
des sparateurs ou des terminateurs
*/
OptSemicol : /* ebnf:print=expand */
/* empty */
{}
| TK_SEMICOL
{}
;
/* ebnf:group=IdentRules */
Pragma: /* e.g., %ASSUME:toto% */
{ [] } /* produces 3 shift reduce conflicts! */
| TK_PCENT TK_IDENT TK_COLON TK_IDENT TK_PCENT Pragma
{ (Pragma(Lxm.str $2, Lxm.str $4))::$6 }
;
%%