%{
/*
* Pix
*
* Copyright (C) 2003, 2010 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include
#include
#include
#include
#include "albumtheme-private.h"
int gth_albumtheme_yylex (void);
void gth_albumtheme_yyerror (const char *fmt, ...);
void gth_albumtheme_yyfatalerror (const char *msg);
int gth_albumtheme_yywrap (void);
#define YY_NO_UNPUT
#define YYERROR_VERBOSE 1
%}
%union {
char *text;
int ivalue;
GthAttribute *attribute;
GthTag *tag;
GthExpr *expr;
GList *list;
GthCondition *cond;
GthLoop *loop;
}
%nonassoc IF ELSE ELSE_IF END SET_VAR PRINT
%token END_TAG
%token VARIABLE ATTRIBUTE_NAME FUNCTION_NAME QUOTED_STRING
%token FOR_EACH
%token NUMBER
%token SET_VAR
%token HTML
%type document
%type tag_command
%type tag_print
%type tag_loop
%type tag_if
%type tag_else_if
%type opt_tag_else
%type opt_tag_else_if
%type attribute_list
%type attribute
%type expr_list
%type expr
%left BOOL_OP
%left COMPARE
%left RANGE IN
%left '+' '-' '*' '/' '!' ','
%right UNARY_OP
%%
all : document {
yy_parsed_doc = $1;
if (yy_parsed_doc == NULL)
YYABORT;
else
YYACCEPT;
}
;
document : HTML document {
$$ = g_list_prepend ($2, gth_tag_new_html ($1));
g_free ($1);
}
| tag_command document {
$$ = g_list_prepend ($2, $1);
}
| tag_print document {
$$ = g_list_prepend ($2, $1);
}
| tag_loop document tag_end document {
GthTag *tag;
gth_loop_add_document ($1, $2);
tag = gth_tag_new_loop ($1);
$$ = g_list_prepend ($4, tag);
}
| tag_if document opt_tag_else_if opt_tag_else tag_end document {
GList *cond_list;
GthTag *tag;
gth_condition_add_document ($1, $2);
cond_list = g_list_prepend ($3, $1);
if ($4 != NULL)
cond_list = g_list_append (cond_list, $4);
tag = gth_tag_new_condition (cond_list);
$$ = g_list_prepend ($6, tag);
}
| /* empty */ {
$$ = NULL;
}
| error document {
/*if ($2 != NULL)
gth_parsed_doc_free ($2);*/
$$ = NULL;
}
;
tag_loop : FOR_EACH VARIABLE END_TAG {
if (g_str_equal ($2, "thumbnail_caption")) {
$$ = gth_loop_new (GTH_TAG_FOR_EACH_THUMBNAIL_CAPTION);
}
else if (g_str_equal ($2, "image_caption")) {
$$ = gth_loop_new (GTH_TAG_FOR_EACH_IMAGE_CAPTION);
}
else {
yyerror ("Wrong iterator: '%s', expected 'thumbnail_caption' or 'image_caption'", $2);
YYERROR;
}
}
| FOR_EACH VARIABLE IN expr RANGE expr END_TAG {
$$ = gth_range_loop_new ();
gth_range_loop_set_range (GTH_RANGE_LOOP ($$), $2, $4, $6);
g_free ($2);
gth_expr_unref ($4);
gth_expr_unref ($6);
}
;
tag_if : IF expr END_TAG {
$$ = gth_condition_new ($2);
}
| IF '"' expr '"' END_TAG {
$$ = gth_condition_new ($3);
}
;
opt_tag_else_if : tag_else_if document opt_tag_else_if {
gth_condition_add_document ($1, $2);
$$ = g_list_prepend ($3, $1);
}
| /* empty */ {
$$ = NULL;
}
;
tag_else_if : ELSE_IF expr END_TAG {
$$ = gth_condition_new ($2);
}
| ELSE_IF '"' expr '"' END_TAG {
$$ = gth_condition_new ($3);
}
;
opt_tag_else : tag_else document {
GthExpr *else_expr;
GthCondition *cond;
else_expr = gth_expr_new ();
gth_expr_push_integer (else_expr, 1);
cond = gth_condition_new (else_expr);
gth_condition_add_document (cond, $2);
$$ = cond;
}
| /* empty */ {
$$ = NULL;
}
;
tag_else : ELSE END_TAG
;
tag_end : END END_TAG
;
tag_command : SET_VAR attribute_list END_TAG {
$$ = gth_tag_new (GTH_TAG_SET_VAR, $2);
}
;
tag_print : PRINT FUNCTION_NAME expr_list END_TAG {
if (gth_tag_get_type_from_name ($2) == GTH_TAG_EVAL) {
GthExpr *e;
GList *arg_list;
if ($3 == NULL) {
yyerror ("Missing argument for function 'eval', expected expression");
YYERROR;
}
e = $3->data;
arg_list = g_list_append (NULL, gth_attribute_new_expression ("expr", e));
$$ = gth_tag_new (GTH_TAG_EVAL, arg_list);
gth_expr_list_unref ($3);
}
else if (gth_tag_get_type_from_name ($2) == GTH_TAG_TRANSLATE) {
GList *arg_list = NULL;
GList *scan;
for (scan = $3; scan; scan = scan->next) {
GthExpr *e = scan->data;
if (scan == $3) {
GthCell *cell;
cell = gth_expr_get (e);
if (cell->type != GTH_CELL_TYPE_STRING) {
yyerror ("Wrong argument type: %d, expected string", cell->type);
YYERROR;
}
arg_list = g_list_append (arg_list, gth_attribute_new_string ("text", cell->value.string->str));
continue;
}
arg_list = g_list_append (arg_list, gth_attribute_new_expression ("expr", e));
}
$$ = gth_tag_new (GTH_TAG_TRANSLATE, arg_list);
gth_expr_list_unref ($3);
}
else {
yyerror ("Wrong function: '%s', expected 'eval' or 'translate'", $2);
YYERROR;
}
}
| PRINT FUNCTION_NAME attribute_list END_TAG {
GthTagType tag_type = gth_tag_get_type_from_name ($2);
if (tag_type == GTH_TAG_INVALID) {
yyerror ("Unrecognized function: %s", $2);
YYERROR;
}
$$ = gth_tag_new (tag_type, $3);
}
;
attribute_list : attribute attribute_list {
$$ = g_list_prepend ($2, $1);
}
| /* empty */ {
$$ = NULL;
}
;
attribute : ATTRIBUTE_NAME '=' '"' expr '"' {
$$ = gth_attribute_new_expression ($1, $4);
g_free ($1);
}
| ATTRIBUTE_NAME '=' '\'' QUOTED_STRING '\'' {
$$ = gth_attribute_new_string ($1, $4);
g_free ($1);
g_free ($4);
}
| ATTRIBUTE_NAME {
GthExpr *e = gth_expr_new ();
gth_expr_push_integer (e, 1);
$$ = gth_attribute_new_expression ($1, e);
g_free ($1);
}
;
expr_list : expr ',' expr_list {
$$ = g_list_prepend ($3, $1);
}
| expr {
$$ = g_list_prepend (NULL, $1);
}
| /* empty */ {
$$ = NULL;
}
;
expr : '(' expr ')' {
$$ = $2;
}
| expr COMPARE expr {
GthExpr *e = gth_expr_new ();
gth_expr_push_expr (e, $1);
gth_expr_push_expr (e, $3);
gth_expr_push_op (e, $2);
gth_expr_unref ($1);
gth_expr_unref ($3);
$$ = e;
}
| expr '+' expr {
GthExpr *e = gth_expr_new ();
gth_expr_push_expr (e, $1);
gth_expr_push_expr (e, $3);
gth_expr_push_op (e, GTH_OP_ADD);
gth_expr_unref ($1);
gth_expr_unref ($3);
$$ = e;
}
| expr '-' expr {
GthExpr *e = gth_expr_new ();
gth_expr_push_expr (e, $1);
gth_expr_push_expr (e, $3);
gth_expr_push_op (e, GTH_OP_SUB);
gth_expr_unref ($1);
gth_expr_unref ($3);
$$ = e;
}
| expr '*' expr {
GthExpr *e = gth_expr_new ();
gth_expr_push_expr (e, $1);
gth_expr_push_expr (e, $3);
gth_expr_push_op (e, GTH_OP_MUL);
gth_expr_unref ($1);
gth_expr_unref ($3);
$$ = e;
}
| expr '/' expr {
GthExpr *e = gth_expr_new ();
gth_expr_push_expr (e, $1);
gth_expr_push_expr (e, $3);
gth_expr_push_op (e, GTH_OP_DIV);
gth_expr_unref ($1);
gth_expr_unref ($3);
$$ = e;
}
| expr BOOL_OP expr {
GthExpr *e = gth_expr_new ();
gth_expr_push_expr (e, $1);
gth_expr_push_expr (e, $3);
gth_expr_push_op (e, $2);
gth_expr_unref ($1);
gth_expr_unref ($3);
$$ = e;
}
| '+' expr %prec UNARY_OP {
$$ = $2;
}
| '-' expr %prec UNARY_OP {
gth_expr_push_op ($2, GTH_OP_NEG);
$$ = $2;
}
| '!' expr %prec UNARY_OP {
gth_expr_push_op ($2, GTH_OP_NOT);
$$ = $2;
}
| VARIABLE '(' expr_list ')' %prec UNARY_OP { /* function call */
GthExpr *e = gth_expr_new ();
gth_expr_push_var (e, $1);
if ($3 != NULL) {
GList *scan;
for (scan = $3; scan; scan = scan->next) {
GthExpr *arg = scan->data;
gth_expr_push_expr (e, arg);
gth_expr_unref (arg);
}
g_list_free ($3);
}
g_free ($1);
$$ = e;
}
| VARIABLE {
GthExpr *e = gth_expr_new ();
gth_expr_push_var (e, $1);
g_free ($1);
$$ = e;
}
| '\'' QUOTED_STRING '\'' {
GthExpr *e = gth_expr_new ();
gth_expr_push_string (e, $2);
g_free ($2);
$$ = e;
}
| NUMBER {
GthExpr *e = gth_expr_new ();
gth_expr_push_integer (e, $1);
$$ = e;
}
;
%%
int
gth_albumtheme_yywrap (void)
{
return 1;
}
void
gth_albumtheme_yyerror (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
fprintf (stderr, "\n");
va_end (ap);
}
void
gth_albumtheme_yyfatalerror (const char *msg)
{
g_error ("%s", msg);
}
#include "albumtheme-lex.c"