-
Erwan Jahier authoredErwan Jahier authored
parser.mly 26.24 KiB
%{
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 immdiat */
| TK_TYPE sxIdent TK_EQ sxType
{
Lxm.flagit
(TypeInfo (AliasedType (Lxm.id $2, $4)))
$2
}
/* type numr */
/* 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 nomms */
/* WARNING ! la liste est dj 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 collectes dans les tables
sont figes, 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
acceptes 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 dfinies :
*/
| 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
acceptes 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 dfinies : */
| 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 immdiat */
| sxIdent TK_EQ sxType
{ treat_aliased_type $1 $3 }
/* type numr */
/* 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 nomms */
/* WARNING ! la liste est dj 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 "immdiat" */
sxType:
/* 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 */
| sxIdentRef { {src=$1.src; it= Named_type_exp $1.it } }
/* ou tableau immdiat */
| 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'entre 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 dclarations de vars types et clockes */
sxVarDeclList: sxVarDecl
{ [$1] }
| sxVarDeclList TK_SEMICOL sxVarDecl
{ $3::$1 }
;
/* dclaration de vars ventuellement clockes */
sxVarDecl:
/*
Pas de clock : sous-entendu sur la base
exemple: x, ..., z : type
*/
sxTypedIdents
{
([$1], Base)
}
|
/*
Clock explicite sur UNE seule liste d'idents typs
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 typs
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:
/* zroaires */
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) }
/* Oprations sur les tableaux */
/* -> cration partir d'une liste */
| TK_OPEN_BRACKET sxExpressionList TK_CLOSE_BRACKET
{ naryexp $1 ARRAY_n (List.rev $2) }
/* -> cration par exponentiation */
| sxExpression TK_HAT sxExpression { binexp $2 HAT_n $1 $3 }
/* -> concatnation */
| sxExpression TK_BAR sxExpression { binexp $2 CONCAT_n $1 $3 }
/* -> accs un lment */
| sxExpression TK_OPEN_BRACKET sxExpression TK_CLOSE_BRACKET
{ unexp $2 (ARRAY_ACCES_n $3) $1 }
/* -> accs 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 }
/* Parenthses */
| 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 rgles 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 prdfini
| 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 rsoudre)
*/
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 ( rsoudre) */
/* 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:
/* 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 */
| 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 cres 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 cres 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 sparateurs 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 }