%{ open Lxm open Predef open SyntaxTree open SyntaxTreeCore open ParserUtils (**********************************************************************************) (**********************************************************************************) (**********************************************************************************) %} %token TK_EOF %token <Lxm.t> TK_ERROR %token <Lxm.t> TK_EXTERN %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_FIELD %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_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_SLICE_START /* %token <Lxm.t> TK_QUOTE */ /* Priorities */ %left TK_ELSE %left TK_BAR %left TK_ARROW %nonassoc TK_STEP %nonassoc TK_CDOTS %left TK_OR TK_XOR %left TK_AND %nonassoc TK_LT TK_LTE TK_EQ TK_GTE TK_GT TK_NEQ TK_IMPL %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 %left TK_HAT TK_FIELD TK_DOT %right TK_OPEN_BRACKET TK_OPEN_BRACE TK_SEMICOL %right TK_COMA %right TK_FBY /* sxEntry point */ %start sxLusFile %type <SyntaxTree.t> sxLusFile %% /*------------------------------------------------------- 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 "sxTotoReverseList". This is why they must not be used in other rules: onr have to use the corresponding "sxTotoList" which finally reverse the list. -------------------------------------------------------*/ /* A lustre file is either an old-fashioned list of item decl, or a list of pack/model declaration */ sxLusFile: /* WARNING ! il faut remettre la liste � l'endroit */ sxIncludeList sxPackBody TK_EOF { SyntaxTree.PRPackBody($1, $2) } | sxIncludeList sxPackList TK_EOF { SyntaxTree.PRPack_or_models ($1, List.rev $2) } ; sxPackList: sxOnePack { [$1] } | sxPackList sxOnePack { $2::$1 } ; sxOnePack: sxModelDecl { SyntaxTree.NSModel $1 } | sxPackDecl { SyntaxTree.NSPack $1 } | sxPackEq { SyntaxTree.NSPack $1 } ; sxInclude: TK_INCLUDE TK_STRING { (Lxm.str $2) } ; sxIncludeList: { [] } | sxInclude sxIncludeList { $1::$2 } ; /* Pour les provides, on rend des decls, bien que syntaxiquement, on n'autorise pas n'importe quoi ... */ sxProvides: /* nada */ { None } /* | TK_PROVIDES sxStaticParamList TK_SEMICOL */ | TK_PROVIDES sxProvideList TK_SEMICOL { Some (List.rev $2) } ; sxProvideList: sxOneProvide { [$1] } | sxProvideList TK_SEMICOL sxOneProvide { $3::$1 } ; sxConstDefOpt: { None} | TK_EQ sxExpression { Some $2 } sxOneProvide: /* constante abstraite */ TK_CONST sxIdent TK_COLON sxType sxConstDefOpt { Lxm.flagit (ConstInfo (ExternalConst (Lxm.id $2, $4, $5))) $2 } /* noeud abstrait */ | TK_NODE sxIdent sxParams TK_RETURNS sxParams { treat_abstract_node true $2 $3 $5 } /* fonction abstraite */ | TK_FUNCTION sxIdent sxParams TK_RETURNS sxParams { treat_abstract_node false $2 $3 $5 } /* type abstrait ... */ | TK_TYPE sxIdent { Lxm.flagit (TypeInfo (ExternalType (Lxm.id $2))) $2 } /* un alias sur type imm�diat */ | TK_TYPE sxIdent TK_EQ sxType { Lxm.flagit (TypeInfo (AliasedType (Lxm.id $2, $4))) $2 } /* type �num�r� */ /* WARNING ! la liste n'est pas � l'endroit */ | TK_TYPE sxIdent TK_EQ TK_ENUM TK_OPEN_BRACE sxIdentList TK_CLOSE_BRACE { let fields = List.rev_map lexeme_to_ident_flagged $6 in Lxm.flagit (TypeInfo (EnumType (Lxm.id $2, fields))) $2 } /* type structure � champs nomm�s */ /* WARNING ! la liste est d�j� � l'endroit */ | TK_TYPE sxIdent TK_EQ opt_TK_STRUCT TK_OPEN_BRACE sxTypedValuedIdents TK_CLOSE_BRACE { let sti = make_struct_type_info $2 $6 in Lxm.flagit (TypeInfo (StructType sti)) $2 } ; sxModelDecl: TK_MODEL sxIdent sxUses /* TK_NEEDS sxPackParamList TK_SEMICOL */ TK_NEEDS sxStaticParamList TK_SEMICOL sxProvides TK_BODY sxPackBody TK_END { let mdecl = { mo_name = (Ident.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 } } ; sxPackDecl: TK_PACKAGE sxIdent sxUses sxProvides TK_BODY sxPackBody TK_END { let pdef = PackGiven { pg_uses = $3 ; pg_provides = $4 ; pg_body = $6; } in let pdecl = { pa_name = (Ident.pack_name_of_string (Lxm.str $2)); pa_def = pdef; } in {it = pdecl; src = $2 } } ; /* pack params are identical to node static Packparams (?) */ /* sxPackParamList: sxStaticParamList { $1 } ; */ sxUses: /* nada */ { [] } | TK_USES sxIdentList TK_SEMICOL { List.rev_map lexeme_to_pack_name_flagged $2 } ; /* */ sxEq_or_Is: | TK_EQ {} | TK_IS {} /* I don't like by-pos notation, but keep it for backward compatibility */ sxPackEq: TK_PACKAGE sxIdent sxEq_or_Is sxIdent TK_OPEN_PAR sxStaticArgList TK_CLOSE_PAR TK_SEMICOL { let pdef = PackInstance { pi_model = (Lxm.id $4); pi_args = (List.rev $6); } in let pa = { pa_name = (Ident.pack_name_of_string (Lxm.str $2)); pa_def = pdef; } in {it = pa; src = $2 } } ; /* sxPackBody : les informations collect�es dans les tables sont fig�es, et on remet les tables � 0 ... */ sxPackBody: sxDeclList { let res = SyntaxTree.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 } ; /* sxDeclarations */ sxDeclList: sxOneDecl { } | sxDeclList sxOneDecl { } ; sxOneDecl: sxConstDecl { } | sxTypeDecl { } | sxExtNodeDecl { } | sxNodeDecl { } ; /* sxIdentifiers and lists */ sxIdentRef : /* simple or long ... */ TK_IDENT { idref_of_lxm $1 } | TK_LONGIDENT { idref_of_lxm $1 } ; /* sxIdentifiers and lists */ sxIdent: TK_IDENT sxPragma { $1 } ; sxIdentList: sxIdent { [$1] } | sxIdentList TK_COMA sxIdent { $3::$1 } ; sxTypedIdentsList: sxTypedIdents { [ $1 ] } | sxTypedIdentsList TK_SEMICOL sxTypedIdents { $3::$1 } ; sxTypedIdents: sxIdentList TK_COLON sxType /* WARNING ! il faut remettre la liste � l'endroit */ { ((List.rev $1), $3 ) } ; sxTypedValuedIdents: sxTypedValuedIdent { $1 } | sxTypedValuedIdents TK_SEMICOL sxTypedValuedIdent { List.append $1 $3 } ; sxTypedValuedIdent : /* Les listes d'idents en partie gauche sont accept�es pour les idents SANS valeur */ sxIdent TK_COLON sxType { (id_valopt_list_of_id_list [$1] $3 ) } | sxIdent TK_COMA sxIdentList TK_COLON sxType { (id_valopt_list_of_id_list ($1::(List.rev $3)) $5) } /* Mais pas pour les constantes d�finies : */ | sxIdent TK_COLON sxType TK_EQ sxExpression { [id_valopt_of_id_val $1 $3 $5] } ; /* constantes */ sxConstDecl: TK_CONST sxConstDeclList {} ; sxConstDeclList: | sxOneConstDecl TK_SEMICOL {} | sxConstDeclList sxOneConstDecl TK_SEMICOL {} ; sxOneConstDecl: /* Les listes d'idents en partie gauche sont accept�es pour les constantes externes : */ | sxIdent TK_COLON sxType { (treat_external_const_list [$1] $3 ) } | sxIdent TK_COMA sxIdentList TK_COLON sxType { (treat_external_const_list ($1::(List.rev $3)) $5) } /* Mais pas pour les constantes d�finies : */ | sxIdent TK_COLON sxType TK_EQ sxExpression { (treat_defined_const $1 (Some $3) $5) } | sxIdent TK_EQ sxExpression { (treat_defined_const $1 (None) $3 ) } ; /* types */ sxTypeDecl: TK_TYPE sxTypeDeclList {} ; sxTypeDeclList: sxOneTypeDecl TK_SEMICOL {} | sxTypeDeclList sxOneTypeDecl TK_SEMICOL {} ; sxOneTypeDecl: /* liste de types abstraits (externes) */ sxIdentList { treat_external_type_list (List.rev $1) } /* un alias sur type imm�diat */ | sxIdent TK_EQ sxType { treat_aliased_type $1 $3 } /* type �num�r� */ /* WARNING ! il faut remettre la liste � l'endroit */ | sxIdent TK_EQ TK_ENUM TK_OPEN_BRACE sxIdentList TK_CLOSE_BRACE { treat_enum_type $1 (List.rev $5) } /* type structure � champs nomm�s */ /* WARNING ! la liste est d�j� � l'endroit */ | sxIdent TK_EQ opt_TK_STRUCT TK_OPEN_BRACE sxTypedValuedIdents TK_CLOSE_BRACE { treat_struct_type $1 $5 } ; /* COMPATIBILITY : "struct" keyword is optional */ opt_TK_STRUCT: /* nothing */ {} | TK_STRUCT {} ; /* Notation de type "imm�diat" */ sxType: /* pr�d�fini */ 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� */ | sxIdentRef { {src=$1.src; it= Named_type_exp $1.it } } /* ou tableau imm�diat */ | sxType TK_HAT sxExpression { {src=$2; it=Array_type_exp ($1 , $3) } } ; /* extern nodes */ sxExtNodeDecl: TK_EXTERN TK_FUNCTION sxIdent sxParams TK_RETURNS sxParams sxOptSemicol { treat_external_node false $3 $4 $6 } | TK_EXTERN TK_NODE sxIdent sxParams TK_RETURNS sxParams sxOptSemicol { treat_external_node true $3 $4 $6 } ; /* noeuds */ sxNodeDecl: sxLocalNode {}; sxLocalNode: | TK_NODE sxIdent sxStaticParams sxParams TK_RETURNS sxParams sxPragma sxOptSemicol sxLocals sxBody sxOptEndNode { treat_node_decl true $2 $3 $4 $6 $9 $7 (fst $10) (snd $10) } | TK_FUNCTION sxIdent sxStaticParams sxParams TK_RETURNS sxParams sxPragma sxOptSemicol sxLocals sxBody sxOptEndNode { treat_node_decl false $2 $3 $4 $6 $9 $7 (fst $10) (snd $10) } | TK_NODE sxIdent sxStaticParams sxNodeProfileOpt TK_EQ sxEffectiveNode sxOptSemicol { treat_node_alias true $2 $3 $4 $6 } ; | TK_FUNCTION sxIdent sxStaticParams sxNodeProfileOpt TK_EQ sxEffectiveNode sxOptSemicol { treat_node_alias false $2 $3 $4 $6 } ; sxNodeProfileOpt : /* nada */ { None } | sxParams TK_RETURNS sxParams { let invars = clocked_ids_to_var_infos VarInput $1 in let outvars = clocked_ids_to_var_infos VarOutput $3 in Some (invars, outvars) } ; sxStaticParams: /*rien*/ { [] } | TK_OPEN_STATIC_PAR sxStaticParamList TK_CLOSE_STATIC_PAR { (List.rev $2) } ; sxStaticParamList: sxStaticParam { [$1] } | sxStaticParamList TK_SEMICOL sxStaticParam { $3::$1 } ; sxStaticParam: TK_TYPE sxIdent { {it=(StaticParamType (Lxm.id $2)); src=$2} } | TK_CONST sxIdent TK_COLON sxType { {it=(StaticParamConst (Lxm.id $2 , $4)); src=$2} } | TK_NODE sxIdent sxParams TK_RETURNS sxParams { 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 ) in Lxm.flagit xn $2 } | TK_FUNCTION sxIdent sxParams TK_RETURNS sxParams { 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 ) in Lxm.flagit xn $2 } ; /* Le "." � la fin des noeuds est une fioriture historique, On accepte donc '.' ';' ou rien du tout ! */ sxOptEndNode: TK_DOT {} | sxOptSemicol {} ; /* Aucune difference entre params d'entr�e et les autres */ /* params de sortie */ sxParams: /* rien */ TK_OPEN_PAR TK_CLOSE_PAR { [] } | TK_OPEN_PAR sxVarDeclList sxOptSemicol TK_CLOSE_PAR /* WARNING ! il faut remettre la liste � l'endroit */ { (List.rev $2) } ; /* variables locales */ sxLocals: /* empty */ { [] } | TK_VAR sxVarDeclList TK_SEMICOL /* WARNING ! il faut remettre la liste � l'endroit */ { (List.rev $2) } ; /* liste de d�clarations de vars typ�es et clock�es */ sxVarDeclList: sxVarDecl { [$1] } | sxVarDeclList TK_SEMICOL sxVarDecl { $3::$1 } ; /* d�claration de vars �ventuellement clock�es */ sxVarDecl: /* Pas de clock : sous-entendu sur la base exemple: x, ..., z : type */ sxTypedIdents { ([$1], Base) } | /* Clock explicite sur UNE seule liste d'idents typ�s exemple: x, ..., z : type when clock */ sxTypedIdents TK_WHEN sxIdent { ([$1], (NamedClock {it=Lxm.id $3; src = $3} )) } | /* Clock explicite sur PLUSIEURS listes d'idents typ�s exemple: (x,..,z : t1 ; a,...,b : t2) when clock */ TK_OPEN_PAR sxTypedIdentsList TK_CLOSE_PAR TK_WHEN sxIdent /* WARNING ! il faut remettre la liste � l'endroit */ { ( (List.rev $2), (NamedClock {it=Lxm.id $5; src=$5} ) ) } ; /* Corps d'un noeud */ /* Retourne un couple (assertions list, equations list) */ sxBody: TK_LET TK_TEL { ([], []) } | TK_LET sxEquationList TK_TEL /* WARNING ! il faut remettre les listes � l'endroit */ { (List.rev (fst $2) , List.rev (snd $2)) } ; /* Equations */ sxEquationList: sxEquation { $1 } | sxPragma sxEquation { $2 } | sxEquationList sxEquation { ( (fst $2) @ (fst $1) , (snd $2) @ (snd $1) ) } ; sxEquation: TK_ASSERT sxExpression TK_SEMICOL { ( [ {src = $1; it = $2} ] , [] ) } | sxLeft TK_EQ sxExpression TK_SEMICOL { ( [] , [ {src = $2; it = ($1, $3) } ] ) } ; /* partie gauche d'equation */ sxLeft: sxLeftItemList /* WARNING ! il faut remettre la liste � l'endroit */ { (List.rev $1) } | TK_OPEN_PAR sxLeftItemList TK_CLOSE_PAR /* WARNING ! il faut remettre la liste � l'endroit */ { (List.rev $2) } ; sxLeftItemList: sxLeftItem { [$1] } | sxLeftItemList TK_COMA sxLeftItem { $3::$1 } ; sxLeftItem: sxIdent { LeftVar ( {src = $1; it = Lxm.id $1} ) } | sxFieldLeftItem { $1 } | sxTableLeftItem { $1 } ; sxFieldLeftItem: sxLeftItem TK_DOT sxIdent { LeftField ($1 , {src = $3; it = Lxm.id $3} ) } ; sxTableLeftItem: sxLeftItem TK_OPEN_BRACKET sxExpression TK_CLOSE_BRACKET { LeftArray ($1 , {src = $2; it = $3}) } | sxLeftItem TK_OPEN_BRACKET sxSelect TK_CLOSE_BRACKET { LeftSlice ($1, $3 ) } ; /* partie droite d'equation (expression) */ sxExpression: /* z�roaires */ sxConstant { $1 } | sxIdentRef { leafexp $1.src (IDENT_n $1.it) } /* unaires */ | TK_NOT sxExpression { unexp_predef $1 NOT_n $2 } | TK_MINUS sxExpression %prec TK_UMINUS { unexp_predef $1 UMINUS_n $2 } | TK_PRE sxExpression { unexp $1 PRE_n $2 } | TK_CURRENT sxExpression { unexp $1 CURRENT_n $2 } | TK_INT sxExpression { unexp_predef $1 REAL2INT_n $2 } | TK_REAL sxExpression { unexp_predef $1 INT2REAL_n $2 } /* binaires */ | sxExpression TK_FBY sxExpression { binexp $2 FBY_n $1 $3 } | sxExpression TK_ARROW sxExpression { binexp $2 ARROW_n $1 $3 } | sxExpression TK_WHEN sxExpression { binexp $2 WHEN_n $1 $3 } | sxExpression TK_AND sxExpression { binexp_predef $2 AND_n $1 $3 } | sxExpression TK_OR sxExpression { binexp_predef $2 OR_n $1 $3 } | sxExpression TK_XOR sxExpression { binexp_predef $2 XOR_n $1 $3 } | sxExpression TK_IMPL sxExpression { binexp_predef $2 IMPL_n $1 $3 } | sxExpression TK_EQ sxExpression { binexp_predef $2 EQ_n $1 $3 } | sxExpression TK_NEQ sxExpression { binexp_predef $2 NEQ_n $1 $3 } | sxExpression TK_LT sxExpression { binexp_predef $2 LT_n $1 $3 } | sxExpression TK_LTE sxExpression { binexp_predef $2 LTE_n $1 $3 } | sxExpression TK_GT sxExpression { binexp_predef $2 GT_n $1 $3 } | sxExpression TK_GTE sxExpression { binexp_predef $2 GTE_n $1 $3 } | sxExpression TK_DIV sxExpression { binexp_predef $2 DIV_n $1 $3 } | sxExpression TK_MOD sxExpression { binexp_predef $2 MOD_n $1 $3 } | sxExpression TK_MINUS sxExpression { binexp_predef $2 MINUS_n $1 $3 } | sxExpression TK_PLUS sxExpression { binexp_predef $2 PLUS_n $1 $3 } | sxExpression TK_SLASH sxExpression { binexp_predef $2 SLASH_n $1 $3 } | sxExpression TK_STAR sxExpression { binexp_predef $2 TIMES_n $1 $3 } /* ternaires */ | TK_IF sxExpression TK_THEN sxExpression TK_ELSE sxExpression { ternexp_predef $1 IF_n $2 $4 $6 } | TK_WITH sxExpression TK_THEN sxExpression TK_ELSE sxExpression { 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 sxExpressionList TK_CLOSE_PAR { naryexp_predef $1 DIESE_n (List.rev $3) } | TK_NOR TK_OPEN_PAR sxExpressionList TK_CLOSE_PAR { naryexp_predef $1 NOR_n (List.rev $3) } | sxCallByPosExpression { $1 } | TK_OPEN_PAR sxExpList2 TK_CLOSE_PAR { naryexp $1 TUPLE_n (List.rev $2) } /* Op�rations sur les tableaux */ /* -> cr�ation � partir d'une liste */ | TK_OPEN_BRACKET sxExpressionList TK_CLOSE_BRACKET { naryexp $1 ARRAY_n (List.rev $2) } /* -> cr�ation par exponentiation */ | sxExpression TK_HAT sxExpression { binexp $2 HAT_n $1 $3 } /* -> concat�nation */ | sxExpression TK_BAR sxExpression { binexp $2 CONCAT_n $1 $3 } /* -> acc�s � un �l�ment */ | sxExpression TK_OPEN_BRACKET sxExpression TK_CLOSE_BRACKET { unexp $2 (ARRAY_ACCES_n $3) $1 } /* -> acc�s � une tranche */ | sxExpression TK_OPEN_BRACKET sxSelect TK_CLOSE_BRACKET { unexp $3.src (ARRAY_SLICE_n $3.it) $1 } /* Acces aux structures */ | sxExpression TK_DOT sxIdent { unexp $2 (STRUCT_ACCESS_n (Lxm.id $3)) $1 } /* Appels par noms */ | sxCallByNameExpression { $1 } /* Parenth�ses */ | TK_OPEN_PAR sxExpression TK_CLOSE_PAR { $2 } ; sxPredefOp: | TK_NOT { {src=$1; it=Predef(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_WHEN { {src=$1; it=WHEN_n} } | TK_AND { {src=$1; it=Predef(AND_n,[]) } } | TK_OR { {src=$1; it=Predef(OR_n,[]) } } | TK_XOR { {src=$1; it=Predef(XOR_n,[]) } } | TK_IMPL { {src=$1; it=Predef(IMPL_n,[]) } } | TK_EQ { {src=$1; it=Predef(EQ_n,[]) } } | TK_NEQ { {src=$1; it=Predef(NEQ_n,[]) } } | TK_LT { {src=$1; it=Predef(LT_n,[]) } } | TK_LTE { {src=$1; it=Predef(LTE_n,[]) } } | TK_GT { {src=$1; it=Predef(GT_n,[]) } } | TK_GTE { {src=$1; it=Predef(GTE_n,[]) } } | TK_DIV { {src=$1; it=Predef(DIV_n,[]) } } | TK_MOD { {src=$1; it=Predef(MOD_n,[]) } } | TK_MINUS { {src=$1; it=Predef(MINUS_n,[]) } } | TK_PLUS { {src=$1; it=Predef(PLUS_n,[]) } } | TK_SLASH { {src=$1; it=Predef(SLASH_n,[]) } } | TK_STAR { {src=$1; it=Predef(TIMES_n,[]) } } | TK_IF { {src=$1; it=Predef(IF_n,[]) } } ; /* Appel fonctionnel par position (classique) */ /* NB On a 2 r�gles � cause des appels �chantillonn� */ sxCallByPosExpression: sxEffectiveNode TK_OPEN_PAR sxExpression TK_CLOSE_PAR { naryexp $1.src (CALL_n $1) [$3] } /* WARNING ! il faut remettre la liste � l'endroit */ | sxEffectiveNode TK_OPEN_PAR sxExpList2 TK_CLOSE_PAR { naryexp $1.src (CALL_n $1) (List.rev $3) } ; /* Effective node : une constrcution qui designe un noeud */ sxEffectiveNode: /* Juste un nom */ sxIdentRef { {src=$1.src; it=(($1.it, [])) } } /* Un nom + des params statiques */ | sxIdentRef TK_OPEN_STATIC_PAR sxStaticArgList TK_CLOSE_STATIC_PAR { {src=$1.src; it=(($1.it, List.rev $3)) } } /* Un operateur pr�d�fini | TK_OPERATOR sxPredefOp,[] { {src=$; it=($2.it, []) } } ; XXX pour l'instant, j'enleve la possibilit� d'avoir (operator +(1,2)). On verra ca plus tard */ sxStaticArgList: sxStaticArg { [$1] } | sxStaticArgList TK_COMA sxStaticArg { $3::$1 } /* let's be permissive... */ | sxStaticArgList TK_SEMICOL sxStaticArg { $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 r�soudre) */ sxStaticArg: /* nature explicite */ | TK_TYPE sxType { {src=$1 ; it=StaticArgType $2 } } | TK_CONST sxExpression { {src=$1 ; it=StaticArgConst $2 } } | TK_NODE sxEffectiveNode { {src=$1 ; it=StaticArgNode (CALL_n $2) } } | TK_FUNCTION sxEffectiveNode { {src=$1 ; it=StaticArgNode (CALL_n $2) } } | sxPredefOp { {src=$1.src; it=StaticArgNode $1.it } } /* un ident OU une expression simple (� r�soudre) */ /* c'est au retour qu'on choisit */ | sxSimpleExp { match $1 with | CallByPos (op, x) -> ( match op.it with | IDENT_n idref -> {src=op.src ; it = StaticArgIdent idref } | _ -> {src=op.src ; it= StaticArgConst $1} ) | CallByName _ -> print_string "*** unexpected static argument\n"; assert false } /* un type sans ambiguite */ | sxSurelyType { {src=$1.src; it=StaticArgType $1} } /* un node sans ambiguite */ | sxSurelyNode { {src=$1.src; it=StaticArgNode (CALL_n $1)} } ; sxSurelyNode: | sxIdentRef TK_OPEN_STATIC_PAR sxStaticArgList TK_CLOSE_STATIC_PAR { {src=$1.src; it=($1.it, List.rev $3) } } ; sxSurelyType: /* pr�d�fini */ 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 imm�diat */ | sxSurelyType TK_HAT sxExpression { {src=$1.src; it = Array_type_exp ($1 , $3) } } ; /* sxSimpleExp = statically evaluable exp */ sxSimpleExp: sxConstant { $1 } | sxIdentRef { leafexp $1.src (IDENT_n $1.it) } | TK_OPEN_PAR sxSimpleExp TK_CLOSE_PAR { $2 } | TK_NOT sxSimpleExp { unexp_predef $1 NOT_n $2 } | TK_MINUS sxSimpleExp %prec TK_UMINUS { unexp_predef $1 UMINUS_n $2 } | sxSimpleExp TK_AND sxSimpleExp { binexp_predef $2 AND_n $1 $3 } | sxSimpleExp TK_OR sxSimpleExp { binexp_predef $2 OR_n $1 $3 } | sxSimpleExp TK_XOR sxSimpleExp { binexp_predef $2 XOR_n $1 $3 } | sxSimpleExp TK_IMPL sxSimpleExp { binexp_predef $2 IMPL_n $1 $3 } | sxSimpleExp TK_EQ sxSimpleExp { binexp_predef $2 EQ_n $1 $3 } | sxSimpleExp TK_NEQ sxSimpleExp { binexp_predef $2 NEQ_n $1 $3 } | sxSimpleExp TK_LT sxSimpleExp { binexp_predef $2 LT_n $1 $3 } | sxSimpleExp TK_LTE sxSimpleExp { binexp_predef $2 LTE_n $1 $3 } | sxSimpleExp TK_GT sxSimpleExp { binexp_predef $2 GT_n $1 $3 } | sxSimpleExp TK_GTE sxSimpleExp { binexp_predef $2 GTE_n $1 $3 } | sxSimpleExp TK_DIV sxSimpleExp { binexp_predef $2 DIV_n $1 $3 } | sxSimpleExp TK_MOD sxSimpleExp { binexp_predef $2 MOD_n $1 $3 } | sxSimpleExp TK_MINUS sxSimpleExp { binexp_predef $2 MINUS_n $1 $3 } | sxSimpleExp TK_PLUS sxSimpleExp { binexp_predef $2 PLUS_n $1 $3 } | sxSimpleExp TK_SLASH sxSimpleExp { binexp_predef $2 SLASH_n $1 $3 } | sxSimpleExp TK_STAR sxSimpleExp { binexp_predef $2 TIMES_n $1 $3 } /* ternaires */ | TK_IF sxSimpleExp TK_THEN sxSimpleExp TK_ELSE sxSimpleExp { ternexp_predef $1 IF_n $2 $4 $6 } ; /* Appel fonctionnel par nom */ /* NB Actuellement, uniquement pour les structures, donc pas de soucis d'�chantillonnage */ sxCallByNameExpression: /* WARNING ! il faut remettre la liste � l'endroit */ sxIdentRef TK_OPEN_BRACE sxCallByNameParamList sxOptSemicol TK_CLOSE_BRACE { bynameexp $1.src (STRUCT_n $1.it) (List.rev $3) } /* on peut avoir une liste vide */ | sxIdentRef TK_OPEN_BRACE TK_CLOSE_BRACE { bynameexp $1.src (STRUCT_n $1.it) ([]) } /* COMPATIBILITY : immediate "struct" without the type name | TK_OPEN_BRACE sxCallByNameParamList sxOptSemicol TK_CLOSE_BRACE { bynameexp $1 STRUCT_anonymous_n (List.rev $2) } */ ; sxCallByNameParamList: sxCallByNameParam { [$1] } | sxCallByNameParamList sepVariant sxCallByNameParam { $3::$1 } ; /* COMPATIBILITY : ',' or ';' */ sepVariant: TK_SEMICOL {} | TK_COMA { Errors.warning $1 "separator mismatch, ';' expected"} ; sxCallByNameParam: sxIdent TK_EQ sxExpression { ({it=Lxm.id $1;src=$1} , $3) } ; /* WARNING ! : les listes sont cr�es � l'envers */ sxExpressionList: sxExpression { [$1] } | sxExpList2 { $1 } ; sxConstant: TK_TRUE { (leafexp $1 (Predef(TRUE_n,[]))) } | TK_FALSE { (leafexp $1 (Predef(FALSE_n,[]))) } | TK_ICONST { (leafexp $1 (Predef((ICONST_n (Lxm.id $1)),[]))) } | TK_RCONST { (leafexp $1 (Predef((RCONST_n (Lxm.id $1)),[]))) } ; /* WARNING ! : les listes sont cr�es � l'envers */ sxExpList2: sxExpressionList TK_COMA sxExpression { $3::$1 } ; sxSelect: sxExpression TK_CDOTS sxExpression sxStep { {it={si_first = $1; si_last = $3 ; si_step = $4 }; src = $2} } | TK_SLICE_START sxExpression sxStep { threat_slice_start $1 $2 $3 } ; sxStep: /* empty */ { None } | TK_STEP sxExpression { Some $2 } ; /* NB SyntaxTree laxiste des listes : quand il n'y a pas d'ambiguit�, les ";" sont vus indifferemment commme des s�parateurs ou des terminateurs */ sxOptSemicol : /* empty */ {} | TK_SEMICOL {} ; sxPragma: /* e.g., %ASSUME:toto% */ { [] } /* produces 3 shift reduce conflicts! */ | TK_PCENT TK_IDENT TK_COLON TK_IDENT TK_PCENT sxPragma { (Pragma(Lxm.str $2, Lxm.str $4))::$6 }