aboutsummaryrefslogtreecommitdiff
path: root/src/meta1-gram.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/meta1-gram.y')
-rw-r--r--src/meta1-gram.y217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/meta1-gram.y b/src/meta1-gram.y
new file mode 100644
index 0000000..8ddcbfb
--- /dev/null
+++ b/src/meta1-gram.y
@@ -0,0 +1,217 @@
+%{
+/* MeTA1 configuration parser for Grecs.
+ Copyright (C) 2007-2011 Sergey Poznyakoff
+
+ Grecs 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 3 of the License, or (at your
+ option) any later version.
+
+ Grecs 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 Grecs. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#include "grecs.h"
+
+int yylex(void);
+int yyerror(char *s);
+
+static struct grecs_node *parse_tree;
+extern int yy_flex_debug;
+%}
+
+%union {
+ struct {
+ grecs_locus_t locus;
+ char *string;
+ } ident;
+ char *string;
+ grecs_value_t svalue, *pvalue;
+ struct grecs_list *list;
+ struct { struct grecs_node *head, *tail; } node_list;
+ struct grecs_node *node;
+}
+
+%token <ident> META1_IDENT
+%token <string> META1_STRING
+%type <node> stmt simple block
+%type <node_list> stmtlist
+%type <pvalue> tag value
+%type <string> string slist
+%type <list> slist0
+%type <list> values list
+%%
+
+input : stmtlist
+ {
+ parse_tree = grecs_node_create(grecs_node_root,
+ &grecs_current_locus);
+ parse_tree->v.texttab = grecs_text_table();
+ grecs_node_bind(parse_tree, $1.head, 1);
+ }
+ ;
+
+stmtlist: stmt
+ {
+ $$.head = $$.tail = $1;
+ }
+ | stmtlist stmt
+ {
+ grecs_node_bind($1.tail, $2, 0);
+ }
+ ;
+
+stmt : simple
+ | block
+ ;
+
+simple : META1_IDENT '=' value opt_sc
+ {
+ $$ = grecs_node_create(grecs_node_stmt,
+ &$1.locus);
+ $$->ident = $1.string;
+ $$->v.value = $3;
+ }
+ ;
+
+block : META1_IDENT tag '{' stmtlist '}' opt_sc
+ {
+ $$ = grecs_node_create(grecs_node_block,
+ &$1.locus);
+ $$->ident = $1.string;
+ $$->v.value = $2;
+ grecs_node_bind($$, $4.head, 1);
+ }
+ ;
+
+tag : /* empty */
+ {
+ $$ = NULL;
+ }
+ | META1_IDENT
+ {
+ $$ = grecs_malloc(sizeof($$[0]));
+ $$->type = GRECS_TYPE_STRING;
+ $$->v.string = $1.string;
+ }
+ ;
+
+value : string
+ {
+ $$ = grecs_malloc(sizeof($$[0]));
+ $$->type = GRECS_TYPE_STRING;
+ $$->v.string = $1;
+ }
+ | list
+ {
+ $$ = grecs_malloc(sizeof($$[0]));
+ $$->type = GRECS_TYPE_LIST;
+ $$->v.list = $1;
+ }
+ ;
+
+string : META1_IDENT
+ {
+ $$ = $1.string;
+ }
+ | slist
+ ;
+
+slist : slist0
+ {
+ struct grecs_list_entry *ep;
+
+ grecs_line_begin();
+ for (ep = $1->head; ep; ep = ep->next) {
+ grecs_line_add(ep->data, strlen(ep->data));
+ free(ep->data);
+ ep->data = NULL;
+ }
+ $$ = grecs_line_finish();
+ grecs_list_free($1);
+ }
+
+slist0 : META1_STRING
+ {
+ $$ = grecs_list_create();
+ grecs_list_append($$, $1);
+ }
+ | slist0 META1_STRING
+ {
+ grecs_list_append($1, $2);
+ $$ = $1;
+ }
+ ;
+
+list : '{' values '}'
+ {
+ $$ = $2;
+ }
+ | '{' values ',' '}'
+ {
+ $$ = $2;
+ }
+ ;
+
+values : value
+ {
+ $$ = grecs_value_list_create();
+ grecs_list_append($$, $1);
+ }
+ | values ',' value
+ {
+ grecs_list_append($1, $3);
+ $$ = $1;
+ }
+ ;
+
+opt_sc : /* empty */
+ | ';'
+ ;
+
+%%
+int
+yyerror(char *s)
+{
+ grecs_error(&grecs_current_locus, 0, "%s", s);
+ return 0;
+}
+
+struct grecs_node *
+grecs_meta1_parser(const char *name, int traceflags)
+{
+ int rc;
+ FILE *fp;
+
+ fp = fopen(name, "r");
+ if (!fp) {
+ grecs_error(NULL, errno, _("Cannot open `%s'"), name);
+ return NULL;
+ }
+ yyset_in(fp);
+
+ yy_flex_debug = traceflags & GRECS_TRACE_LEX;
+ yydebug = traceflags & GRECS_TRACE_GRAM;
+ parse_tree = NULL;
+ grecs_line_acc_create();
+ rc = yyparse();
+ fclose(fp);
+ if (grecs_error_count)
+ rc = 1;
+ grecs_line_acc_free();
+ if (rc) {
+ grecs_tree_free(parse_tree);
+ parse_tree = NULL;
+ }
+ return parse_tree;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.