|
|
%{ #include "bnparse.h" // disable warning C4102: unreferenced label #pragma warning (disable : 4102) %}
%token tokenEOF 0 %token tokenNil %token tokenError
%token <zsr> tokenIdent tokenString %token <ui> tokenInteger %token <real> tokenReal
/* key words */ %token tokenArray %token tokenContinuous %token tokenCreator %token tokenDefault %token tokenDiscrete %token tokenFormat %token tokenFunction %token tokenImport %token tokenIs %token tokenKeyword %token tokenLeak %token tokenNA %token tokenName %token tokenNamed %token tokenNetwork %token tokenNode %token tokenOf %token tokenParent %token tokenPosition %token tokenProbability %token tokenProperties %token tokenProperty %token tokenPropIdent %token tokenStandard %token tokenState %token tokenType %token tokenUser %token tokenVersion %token tokenWordChoice %token tokenWordReal %token tokenWordString
%token tokenAs %token tokenLevel %token tokenDomain %token tokenDistribution %token tokenDecisionGraph %token tokenBranch %token tokenOn %token tokenLeaf %token tokenVertex %token tokenMultinoulli %token tokenMerge %token tokenWith %token tokenFor %token tokenRangeOp /* ".." */
%type <ui> proptype dpientry %type <integer> signedint %type <zsr> tokentoken tokenPropIdent proptypename tokenlistel %type <zsr> creator name format %type <real> real signedreal version %left '+' '-' %left '*' '/' %right '^' %left UNARY
%start start
%% start : { yyclearin; } bnfile ;
bnfile : header blocklst ;
blocklst : block | blocklst block ;
block : propblock | nodeblock | probblock | domainblock | distblock | ignoreblock ;
header : headerhead headerbody ;
headerhead : tokenNetwork tokentoken { SetNetworkSymb($2); } | tokenNetwork ; headerbody : '{' { _eBlk = EBLKNET; } netdeclst '}' { _eBlk = EBLKNONE; } ;
netdeclst : /* empty */ | netdeclst netdecl ;
netdecl : format { SetFormat($1); } | version { SetVersion($1); } | creator { SetCreator($1); } ;
conj : ':' /* general conjunction */ | '=' | tokenIs ;
prep : tokenWith /* general preposition */ | tokenOn ;
prepopt : prep /* optional preposition */ | /* empty */ ;
/* header block productions */ format : tokenFormat conj tokenString ';' { $$ = $3; } ;
version : tokenVersion conj real ';' { $$ = $3; } ;
creator : tokenCreator conj tokenString ';' { $$ = $3; } ;
/* unrecognized block productions */ ignoreblock : tokenIdent parenexpr_opt { _eBlk = EBLKIGN; WarningSkip($1); } '{' { SkipUntil("}"); } '}' { _eBlk = EBLKNONE; } ;
parenexpr_opt : /* empty */ | '(' { SkipUntil(")"); } ')' ;
/* node block productions */ nodeblock : tokenNode tokenIdent { _eBlk = EBLKNODE; StartNodeDecl($2); } '{' ndattrlst '}' { CheckNodeInfo(); _eBlk = EBLKNONE; } ;
ndattrlst : /* empty */ | ndattrlst ndattr ';' ;
ndattr : name | type | position | property | error ;
name : tokenName conj tokenString { SetNodeFullName($3); } ;
type : tokenType conj tokenDiscrete statedef ;
statedef : tokenDomain tokentoken { SetNodeDomain($2); } | '[' tokenInteger ']' conj_opt { SetNodeCstate($2); } states_opt ;
conj_opt : /* empty */ | conj ;
states_opt : /* empty */ | '{' { ClearCstr(); } tokenlist '}' { SetStates(); } ;
tokenlist : /* empty */ | tokenlistel | tokenlist ',' tokenlistel ; tokenlistel : tokentoken { AddStr($1); } ; tokentoken : tokenIdent | tokenString ;
tokenList : '[' { ClearCstr(); } tokenlist ']' ; ;
position : tokenPosition conj '(' signedint ',' signedint ')' { SetNodePosition($4, $6); } ;
/* probability block productions */ probblock : tokenProbability { _eBlk = EBLKPROB; ClearNodeInfo(); } '(' tokenIdent { SetNodeSymb($4, false); } parentlst_opt ')' { CheckParentList(); } probblocktail { _eBlk = EBLKNONE; } ; /* tail of probability block: may be empty or may be a reference to a distribution */ probblocktail : probblkdistref ';' | ';' { EmptyProbEntries(); } | '{' funcattr_opt { InitProbEntries(); } probentrylst { CheckProbEntries(); } '}' ;
parentlst_opt : /* empty */ | '|' parentlst | error ;
parentlst : tokenIdent { AddSymb($1); } | parentlst ',' tokenIdent { AddSymb($3); } ;
probblkdistref : conj tokenDistribution tokenIdent distplist_opt ;
distplist_opt : /* empty */ | '(' distplist ')' ; distplist : tokenIdent | distplist ',' tokenIdent ;
funcattr_opt : /* empty */ | tokenFunction conj tokenIdent ';' { CheckCIFunc($3); } ;
probentrylst : /* empty */ | probentrylst probentry ;
probentry : dpi doproblst ';' | dpi pdf ';' ;
dpi : /* empty */ { _vui.clear(); CheckDPI(false); } | '(' dodpilst ')' conj { CheckDPI(false); } | tokenDefault conj { CheckDPI(true); } ;
dodpilst : { _vui.clear(); } dpilst ;
dpilst : /* empty */ | dpientry { AddUi($1); } | dpilst ',' dpientry { AddUi($3); } ;
dpientry : tokenInteger { $$ = UiDpi($1); } | tokenIdent { $$ = UiDpi($1); } | tokenString { $$ = UiDpi($1); } ;
doproblst : { _vreal.clear(); } reallst { CheckProbVector(); } ;
pdf : tokenIdent '(' exprlst_opt ')' { CheckPDF($1); } ;
exprlst_opt : /* empty */ | exprlst ;
exprlst : expr | exprlst ',' expr ;
reallst : signedreal { AddReal($1); } | reallst ',' signedreal { AddReal($3); } ;
signedint : '-' tokenInteger { $$ = -INT($2); } | '+' tokenInteger { $$ = +INT($2); } | tokenInteger { $$ = INT($1); } ;
signedreal : '-' real { $$ = -$2; } | '+' real { $$ = $2; } | real | tokenNA { $$ = -1; } ;
real : tokenReal { $$ = $1; } | tokenInteger { $$ = REAL($1); } ;
expr : '(' expr ')' | expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '^' expr | tokenIdent { CheckIdent($1); } | real | tokenString | '-' expr %prec UNARY | '+' expr %prec UNARY ;
/* property declarations block productions */ propblock : tokenProperties '{' { StartProperties(); } propdecllst '}' { EndProperties(); } ;
propdecllst : /* empty */ | propdecllst propitem ';' ; propitem : propimport | propdecl | property ; propimport : tokenImport tokenStandard { ImportPropStandard(); } | tokenImport proptypename { ImportProp($2); } ;
propdecl : tokenType proptypename conj proptype ',' tokenString { AddPropType($2, $4, $6); } | tokenType proptypename conj proptype { AddPropType($2, $4, ZSREF()); } ;
proptype : tokenArray tokenOf tokenWordString { $$ = fPropString | fPropArray; } | tokenArray tokenOf tokenWordReal { $$ = fPropArray; } | tokenWordString { $$ = fPropString; } | tokenWordReal { $$ = 0; } | tokenWordChoice tokenOf tokenList { $$ = fPropChoice; } ;
/* A duplicate property type declaration will cause a tokenIdent to be read as a tokenPropIdent */ proptypename : tokenIdent /* ident not previously seen */ | tokenPropIdent /* error case */ ;
/* property item productions */ property : tokenProperty tokenPropIdent conj { ClearVpv(); } propval { CheckProperty($2); } | tokenProperty tokenIdent conj propval /* error case */ | tokenPropIdent conj { ClearVpv(); } propval { CheckProperty($1); } ;
propval : '[' propvallst ']' | propvalitem ;
propvallst : propvalitem | propvallst ',' propvalitem ;
propvalitem : tokenString { AddPropVar( $1 ); } | tokenIdent { AddPropVar( $1 ); } | signedreal { AddPropVar( $1 ); } ;
/* domain declarations */ domainblock : tokenDomain { ClearDomain(); } tokentoken domainbody { CheckDomain( $3 ); } ;
/* array of domain specifiers */ domainbody : '{' domaindeclst '}' ;
domaindeclst : /* empty */ | domaindec | domaindeclst ',' domaindec ; /* range followed by symbolic name or just symbolic name */ domaindec : rangespec conj tokentoken { AddRange($3, false ); } | tokentoken { AddRange($1, true ); } ;
/* Pascal-style range declaration */ /* variants of range specifiers for open and closed intervals */ /* identifiers are allowed for use with distributions where domains may be known in advance */ rangespec : real tokenRangeOp real /* 0.0 .. 1.0 */ { SetRanges( true, $1, true, $3 ); } | tokentoken tokenRangeOp tokentoken /* lname .. uname */ { SetRanges( $1, $3 ); } | tokenRangeOp real /* .. 1.0 */ { SetRanges( false, 0.0, true, $2 ); } | tokenRangeOp tokentoken /* .. uname */ { SetRanges( ZSREF(), $2 ); } | real tokenRangeOp /* 0.0 .. */ { SetRanges( true, $1, false, 0.0 ); } | tokentoken tokenRangeOp /* lname .. */ { SetRanges( $1, ZSREF() ); } | real /* 0.0 */ { SetRanges( true, $1, true, $1 ); } | tokentoken /* name */ { SetRanges( $1, $1 ); } ;
/* List of range specifiers */ rangedeclst : '(' rangedeclset ')' ; rangedeclset : /* empty */ | rangespec | rangedeclset ',' rangespec ;
/* Advanced distribution declarations */ /* Only "decision graph" for now */
distblock : tokenDistribution /* "distribution" */ tokenDecisionGraph /* "decisionGraph" */ distdeclproto /* pseudo-prototype parent list */ dgraphbody /* body of decision graph items */ ; distdeclproto : tokentoken /* name of distribution */ '(' distdeclst /* pseudo-parent list */ ')' ;
distdeclst : /* empty */ | distdecl | distdeclst ',' distdecl ;
distdecl : tokenIdent tokenAs tokentoken /* pseudo-parent and domain name*/ | tokenIdent /* pseudo-parent name only */ ;
/* Decision graph/tree item declarations */ dgraphbody : '{' dgraphitemlst '}' ;
dgraphitemlst : /* empty */ | dgraphitem | dgraphitemlst ',' dgraphitem ;
/* decision graph/tree item. Vertices and leaves may have names for later merging. Branches and merges have contraint ranges, which are lists of Pascal-style ranges; e.g. ( 3..5, 9, 10, 20.. ) */ dgraphitem : /* vertex */ dgitemlevel tokenVertex tokentoken dgnamed | /* branch */ dgitemlevel tokenBranch prepopt rangedeclst | /* leaf */ dgitemlevel tokenLeaf dgitemleaf dgnamed | /* merge */ dgitemlevel tokenMerge prepopt tokentoken prepopt rangedeclst ;
dgitemlevel : tokenLevel tokenInteger ;
dgitemleaf : tokenMultinoulli '(' reallst ')' ;
/* "named" sub-clause for verticies and leaves */ dgnamed : /* empty */ | tokenNamed tokentoken ; %%
|