%{
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include "out.h"
#include "stable.h"
#include "literals.h"
#include "lut.h"
#include "esclex.h"
#include "tree.h"
%}
%union {
struct tokstr tok;
struct node *np;
}
%right '='
%right '?'
%nonassoc ':'
%left OR
%left AND
%left '|'
%left '^'
%left '&'
%left EQ NE
%left LE GE '<' '>'
%left LSHIFT RSHIFT
%left '-' '+'
%left '*' '%' DIV '/'
%right '!' '~'
%left '.'
%token <tok> PROP MASK ARROW EVENT ENGINE ASRU FRU COUNT CONFIG
%token <tok> ID QUOTE NUMBER IF PATHFUNC
%type <tok> enameid
%type <np> root stmtlist stmt nvpairlist nvpair nvname nvexpr
%type <np> exprlist expr iterid ename pname epname eexprlist ipname iname
%type <np> numexpr cexpr func pfunc parglist parg
%type <np> eventlist event nork norkexpr globid propbody
%%
root : stmtlist
{ (void)tree_root($1); }
;
stmtlist :
{ $$ = NULL; }
| stmtlist stmt
{ $$ = tree_expr(T_LIST, $1, $2); }
;
stmt : error ';'
{ $$ = tree_nothing(); }
| IF '(' expr ')' stmt
{ $$ = $5; }
| IF '(' expr ')' '{' stmtlist '}'
{ $$ = $6; }
| EVENT event nvpairlist ';'
{ $$ = tree_decl(T_EVENT, $2, $3, $1.file, $1.line); }
| ENGINE event nvpairlist ';'
{ $$ = tree_decl(T_ENGINE, $2, $3, $1.file, $1.line); }
| PROP propbody ';'
{
$$ = tree_stmt(T_PROP, $2, $1.file, $1.line);
}
| MASK propbody ';'
{
$$ = tree_stmt(T_MASK, $2, $1.file, $1.line);
}
| ASRU pname nvpairlist ';'
{
$$ = tree_decl(T_ASRU, $2, $3, $1.file, $1.line);
}
| FRU pname nvpairlist ';'
{
$$ = tree_decl(T_FRU, $2, $3, $1.file, $1.line);
}
| CONFIG ipname nvpairlist ';'
{
$$ = tree_decl(T_CONFIG, $2, $3, $1.file, $1.line);
}
| ';'
{ $$ = tree_nothing(); }
;
propbody: eventlist nork ARROW nork eventlist
{
$$ = tree_arrow($1, $2, $4, $5);
}
| propbody nork ARROW nork eventlist
{
$$ = tree_arrow($1, $2, $4, $5);
}
;
nork :
{ $$ = NULL; }
| '(' norkexpr ')'
{ $$ = $2; }
;
norkexpr: NUMBER
{ $$ = tree_num($1.s, $1.file, $1.line); }
| ID
{ $$ = tree_name($1.s, IT_NONE, $1.file, $1.line); }
| '(' norkexpr ')'
{ $$ = $2; }
| norkexpr '-' norkexpr
{ $$ = tree_expr(T_SUB, $1, $3); }
| norkexpr '+' norkexpr
{ $$ = tree_expr(T_ADD, $1, $3); }
| norkexpr '*' norkexpr
{ $$ = tree_expr(T_MUL, $1, $3); }
| norkexpr DIV norkexpr
{ $$ = tree_expr(T_DIV, $1, $3); }
| norkexpr '%' norkexpr
{ $$ = tree_expr(T_MOD, $1, $3); }
;
nvpairlist:
{ $$ = NULL; }
| nvpair
| nvpairlist ',' nvpair
{ $$ = tree_expr(T_LIST, $1, $3); }
;
nvpair : nvname '=' nvexpr
{ $$ = tree_expr(T_NVPAIR, $1, $3); }
| ENGINE '=' nvexpr
{
$$ = tree_expr(T_NVPAIR,
tree_name($1.s, IT_NONE, $1.file, $1.line), $3);
}
| COUNT '=' nvexpr
{
$$ = tree_expr(T_NVPAIR,
tree_name($1.s, IT_NONE, $1.file, $1.line), $3);
}
;
nvname : ID
{ $$ = tree_name($1.s, IT_NONE, $1.file, $1.line); }
| nvname '-' ID
{
$$ = tree_name_repairdash($1, $3.s);
}
;
nvexpr : numexpr
| ename epname
{ $$ = tree_event($1, $2, NULL); }
| pname
| globid
| func
| NUMBER ID
{ $$ = tree_timeval($1.s, $2.s, $1.file, $1.line); }
| QUOTE
{ $$ = tree_quote($1.s, $1.file, $1.line); }
;
numexpr : numexpr '-' numexpr
{ $$ = tree_expr(T_SUB, $1, $3); }
| numexpr '+' numexpr
{ $$ = tree_expr(T_ADD, $1, $3); }
| numexpr '*' numexpr
{ $$ = tree_expr(T_MUL, $1, $3); }
| numexpr DIV numexpr
{ $$ = tree_expr(T_DIV, $1, $3); }
| numexpr '/' numexpr
{ $$ = tree_expr(T_DIV, $1, $3); }
| numexpr '%' numexpr
{ $$ = tree_expr(T_MOD, $1, $3); }
| '(' numexpr ')'
{ $$ = $2; }
| NUMBER
{ $$ = tree_num($1.s, $1.file, $1.line); }
;
eventlist: event
| eventlist ',' event
{ $$ = tree_expr(T_LIST, $1, $3); }
;
event : ename epname eexprlist
{ $$ = tree_event($1, $2, $3); }
;
epname :
{ $$ = NULL; }
| '@' pname
{ $$ = $2; }
;
eexprlist:
{ $$ = NULL; }
| '{' exprlist '}'
{ $$ = $2; }
;
exprlist: expr
| exprlist ',' expr
{ $$ = tree_expr(T_LIST, $1, $3); }
;
expr : cexpr
| NUMBER ID
{ $$ = tree_timeval($1.s, $2.s, $1.file, $1.line); }
;
cexpr : cexpr '=' cexpr
{ $$ = tree_expr(T_ASSIGN, $1, $3); }
| cexpr '?' cexpr
{ $$ = tree_expr(T_CONDIF, $1, $3); }
| cexpr ':' cexpr
{ $$ = tree_expr(T_CONDELSE, $1, $3); }
| cexpr OR cexpr
{ $$ = tree_expr(T_OR, $1, $3); }
| cexpr AND cexpr
{ $$ = tree_expr(T_AND, $1, $3); }
| cexpr '|' cexpr
{ $$ = tree_expr(T_BITOR, $1, $3); }
| cexpr '^' cexpr
{ $$ = tree_expr(T_BITXOR, $1, $3); }
| cexpr '&' cexpr
{ $$ = tree_expr(T_BITAND, $1, $3); }
| cexpr EQ cexpr
{ $$ = tree_expr(T_EQ, $1, $3); }
| cexpr NE cexpr
{ $$ = tree_expr(T_NE, $1, $3); }
| cexpr '<' cexpr
{ $$ = tree_expr(T_LT, $1, $3); }
| cexpr LE cexpr
{ $$ = tree_expr(T_LE, $1, $3); }
| cexpr '>' cexpr
{ $$ = tree_expr(T_GT, $1, $3); }
| cexpr GE cexpr
{ $$ = tree_expr(T_GE, $1, $3); }
| cexpr LSHIFT cexpr
{ $$ = tree_expr(T_LSHIFT, $1, $3); }
| cexpr RSHIFT cexpr
{ $$ = tree_expr(T_RSHIFT, $1, $3); }
| cexpr '-' cexpr
{ $$ = tree_expr(T_SUB, $1, $3); }
| cexpr '+' cexpr
{ $$ = tree_expr(T_ADD, $1, $3); }
| cexpr '*' cexpr
{ $$ = tree_expr(T_MUL, $1, $3); }
| cexpr DIV cexpr
{ $$ = tree_expr(T_DIV, $1, $3); }
| cexpr '/' cexpr
{ $$ = tree_expr(T_DIV, $1, $3); }
| cexpr '%' cexpr
{ $$ = tree_expr(T_MOD, $1, $3); }
| '!' cexpr
{ $$ = tree_expr(T_NOT, $2, NULL); }
| '~' cexpr
{ $$ = tree_expr(T_BITNOT, $2, NULL); }
| '(' cexpr ')'
{ $$ = $2; }
| func
| NUMBER
{ $$ = tree_num($1.s, $1.file, $1.line); }
| ID
{
$$ = tree_name($1.s, IT_NONE, $1.file, $1.line);
}
| globid
| QUOTE
{ $$ = tree_quote($1.s, $1.file, $1.line); }
;
func : ID '(' ')'
{ $$ = tree_func($1.s, NULL, $1.file, $1.line); }
| ID '(' exprlist ')'
{ $$ = tree_func($1.s, $3, $1.file, $1.line); }
| PATHFUNC '(' parglist ')'
{ $$ = tree_func($1.s, $3, $1.file, $1.line); }
| pfunc
;
parglist: parg
| parglist ',' parg
{ $$ = tree_expr(T_LIST, $1, $3); }
;
parg : pfunc
| pname
{ $$ = tree_pname($1); }
| QUOTE
{ $$ = tree_quote($1.s, $1.file, $1.line); }
| ID '(' exprlist ')'
{ $$ = tree_func($1.s, $3, $1.file, $1.line); }
;
pfunc : ASRU '(' pname ')'
{ $$ = tree_func($1.s, tree_pname($3), $1.file, $1.line); }
| FRU '(' pname ')'
{ $$ = tree_func($1.s, tree_pname($3), $1.file, $1.line); }
| COUNT '(' event ')'
{ $$ = tree_func($1.s, $3, $1.file, $1.line); }
;
globid : '$' ID
{ $$ = tree_globid($2.s, $2.file, $2.line); }
;
iterid : ID
{ $$ = tree_name($1.s, IT_VERTICAL, $1.file, $1.line); }
| ID '[' ']'
{ $$ = tree_name($1.s, IT_VERTICAL, $1.file, $1.line); }
| ID '[' cexpr ']'
{
$$ = tree_name_iterator(
tree_name($1.s, IT_VERTICAL, $1.file, $1.line), $3);
}
| ID '<' '>'
{ $$ = tree_name($1.s, IT_HORIZONTAL, $1.file, $1.line); }
| ID '<' ID '>'
{
$$ = tree_name_iterator(
tree_name($1.s, IT_HORIZONTAL, $1.file, $1.line),
tree_name($3.s, IT_NONE, $3.file, $3.line));
}
| ID '-' iterid
{
$$ = tree_name_repairdash2($1.s, $3);
}
;
iname : ID
{ $$ = tree_iname($1.s, $1.file, $1.line); }
;
ename : ID '.' enameid
{
$$ = tree_name_append(
tree_name($1.s, IT_ENAME, $1.file, $1.line),
tree_name($3.s, IT_NONE, $3.file, $3.line));
}
| ename '.' enameid
{
$$ = tree_name_append($1,
tree_name($3.s, IT_NONE, $3.file, $3.line));
}
| ename '-' enameid
{
$$ = tree_name_repairdash($1, $3.s);
}
;
enameid : ID
| PROP
| MASK
| EVENT
| ENGINE
| ASRU
| FRU
| CONFIG
| IF
;
pname : iterid
| pname '/' iterid
{ $$ = tree_name_append($1, $3); }
;
ipname : iname
| ipname '/' iname
{ $$ = tree_name_append($1, $3); }
;
%%