static Template curTmpl;
extern int tmpl_yylineno;
+static TemplateNode newExpressionNode(char *op, GList *args);
+static GList *makeList2(void *a, void *b);
+
%}
%union {
- char *str;
- char punct;
- int varname;
- int flags;
- TemplateNode node;
+ char *str;
+ char punct;
+ int flags;
+ int intval;
+ double floatval;
+ TemplateNode node;
+ GList *list;
}
%type <node> node
%type <node> listnodes
%type <node> template
-%type <node> condition
-%type <node> condition_varname
+%type <node> expression
+%type <list> list_expression
%type <str> varname
%type <flags> opt_escape
-%type <flags> opt_global
-%type <str> opt_default
%type <str> opt_format
+%type <str> opt_default
-%token <str> OR_P
%token <str> STRING
%token <str> FILENAME
%token <str> TEXT_P
%token <str> VAR_OPEN VAR_CLOSE EXPR_OPEN EXPR_CLOSE
INCLUDE_OPEN INCLUDE_CLOSE
%token <str> HTMLESCAPE URLESCAPE IF_P ELSE_P LOOP_P ENDIF_P ENDLOOP_P
- NOT_P DEFINED_P
+%token <str> CMP_P
+
+%token <intval> INTEGER
+%token <floatval> DOUBLE
+
+
+%left '+' '-'
+%left '*' '/' '%'
+%left '?' ':'
+%left NEG
+
+%left OR_P
+%left AND_P
+%left NOT_P
+
+%left CMP_P
%%
| LOOP_P
| ENDIF_P
| ENDLOOP_P
- | NOT_P
- | DEFINED_P
;
opt_escape:
| { $$=0; }
;
-opt_global:
- '^' { $$=TND_GLOBAL; }
- | { $$=0; }
- ;
-
opt_format:
',' STRING { $$=$2; }
| { $$=NULL; }
;
opt_default:
- OR_P STRING { $$=$2; }
+ '#' STRING { $$=$2; }
| { $$=NULL; }
;
-condition_varname:
- varname {
- $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
- $$->type = ConditionNode;
- $$->nodeData.condition.varName = $1;
- $$->nodeData.condition.varNameLength = strlen($1);
- }
- | '^' varname {
- $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
- $$->type = ConditionNode;
- $$->nodeData.condition.flags = TND_GLOBAL;
- $$->nodeData.condition.varName = $2;
- $$->nodeData.condition.varNameLength = strlen($2);
+list_expression:
+ expression ',' expression {
+ $$ = makeList2($1, $3);
}
+ | list_expression ',' expression {
+ $$ = GListPush($$, $3);
+ }
;
-condition:
- condition_varname {
- $$ = $1;
+expression:
+ varname {
+ $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ $$->type = VariableNode;
+ $$->nodeData.variable.varName = $1;
+ $$->nodeData.variable.varNameLength = strlen($1);
+ }
+ | '^' varname {
+ $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ $$->type = VariableNode;
+ $$->nodeData.variable.flags = TND_GLOBAL;
+ $$->nodeData.variable.varName = $2;
+ $$->nodeData.variable.varNameLength = strlen($2);
+ }
+ | STRING {
+ $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ $$->type = ConstNode;
+ $$->nodeData.value.type = valueString;
+ $$->nodeData.value.flags = TND_DEFINED;
+ $$->nodeData.value.value.stringValue = $1;
+ }
+ | INTEGER {
+ $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ $$->type = ConstNode;
+ $$->nodeData.value.type = valueInt;
+ $$->nodeData.value.flags = TND_DEFINED;
+ $$->nodeData.value.value.intValue = $1;
+ }
+ | DOUBLE {
+ $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ $$->type = ConstNode;
+ $$->nodeData.value.type = valueDouble;
+ $$->nodeData.value.flags = TND_DEFINED;
+ $$->nodeData.value.value.doubleValue = $1;
}
- | DEFINED_P condition_varname {
- $$ = $2;
- $$->nodeData.condition.flags |= TND_DEFINED;
+ | expression '+' expression {
+ $$ = newExpressionNode( "+", makeList2( $1, $3 ) );
}
- | NOT_P condition {
- $$ = $2;
- if ( $$->nodeData.condition.flags & TND_NOT )
- $$->nodeData.condition.flags &= ~TND_NOT;
- else
- $$->nodeData.condition.flags |= TND_NOT;
+ | expression '-' expression {
+ $$ = newExpressionNode( "-", makeList2( $1, $3 ) );
}
+ | expression '*' expression {
+ $$ = newExpressionNode( "*", makeList2( $1, $3 ) );
+ }
+ | expression '/' expression {
+ $$ = newExpressionNode( "/", makeList2( $1, $3 ) );
+ }
+ | expression '%' expression {
+ $$ = newExpressionNode( "%", makeList2( $1, $3 ) );
+ }
+ | '-' expression %prec NEG {
+ $$ = newExpressionNode( "-", GListPush( NULL, $2 ) );
+ }
+ | expression AND_P expression {
+ $$ = newExpressionNode( "&&", makeList2( $1, $3 ) );
+ }
+ | expression OR_P expression {
+ $$ = newExpressionNode( "||", makeList2( $1, $3 ) );
+ }
+ | expression '?' expression ':' expression {
+ $$ = newExpressionNode( "?", GListPush( makeList2( $1, $3 ), $5 ) );
+ }
+ | NOT_P expression {
+ $$ = newExpressionNode( "!", GListPush( NULL, $2 ) );
+ }
+ | expression CMP_P expression {
+ $$ = newExpressionNode( $2, makeList2( $1, $3 ) );
+ }
+ | varname '(' ')' {
+ $$ = newExpressionNode( $1, NULL );
+ }
+ | varname '(' expression ')' {
+ $$ = newExpressionNode( $1, GListPush( NULL, $3 ) );
+ }
+ | varname '(' list_expression ')' {
+ $$ = newExpressionNode( $1, $3 );
+ }
+ | '(' expression ')' { $$=$2; }
;
node:
$$->nodeData.text.value = $1;
$$->nodeData.text.valueLength = strlen($1);
}
- | VAR_OPEN opt_global varname opt_format opt_default opt_escape VAR_CLOSE {
+ | VAR_OPEN expression opt_format opt_default opt_escape VAR_CLOSE {
$$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
- $$->type = VariableNode;
- $$->nodeData.variable.varName = $3;
- $$->nodeData.variable.varNameLength = strlen($3);
- $$->nodeData.variable.formatValue = $4;
- $$->nodeData.variable.defaultValue = $5;
- $$->nodeData.variable.flags = $2 | $6;
+ $$->type = PrintNode;
+ $$->nodeData.print.expressionNode = $2;
+ $$->nodeData.print.formatValue = $3;
+ $$->nodeData.print.defaultValue = $4;
+ $$->nodeData.print.flags = $5;
}
| INCLUDE_OPEN FILENAME INCLUDE_CLOSE {
$$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
$$->nodeData.loop.varNameLength = strlen($3);
$$->nodeData.loop.bodyNode = $5;
}
- | EXPR_OPEN IF_P condition EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
- $$ = $3;
+ | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
+ $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ $$->type = ConditionNode;
+ $$->nodeData.condition.expressionNode = $3;
$$->nodeData.condition.ifNode = $5;
}
- | EXPR_OPEN IF_P condition EXPR_CLOSE listnodes EXPR_OPEN ELSE_P EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
- $$ = $3;
+ | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes EXPR_OPEN ELSE_P EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
+ $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ $$->type = ConditionNode;
+ $$->nodeData.condition.expressionNode = $3;
$$->nodeData.condition.ifNode = $5;
$$->nodeData.condition.elseNode = $9;
}
return err;
}
+static TemplateNode
+newExpressionNode(char *op, GList *args) {
+ TemplateNode res;
+
+ res = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
+ res->type = ExpressionNode;
+ res->nodeData.expression.functionName = op;
+ res->nodeData.expression.argsNode = args;
+
+ return res;
+}
+
+static GList *
+makeList2(void *a, void *b) {
+ return GListPush( GListPush(NULL, a), b );
+}