Add expressions
[tedtools.git] / tmpl_gram.y
index 3730660..3335903 100644 (file)
@@ -16,30 +16,33 @@ void startTemplateLex(Template tmpl, FILE *in);
 
 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
@@ -47,7 +50,22 @@ extern int tmpl_yylineno;
 %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
 
 %%
 
@@ -80,8 +98,6 @@ varname:
        | LOOP_P
        | ENDIF_P
        | ENDLOOP_P
-       | NOT_P
-       | DEFINED_P
        ;
 
 opt_escape:
@@ -90,52 +106,103 @@ 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:  
@@ -145,14 +212,13 @@ 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) );
@@ -166,12 +232,16 @@ node:
                                $$->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;
                }
@@ -208,3 +278,19 @@ parseTemplateFile(Template tmpl, char* filename ) {
        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 );
+}