summaryrefslogtreecommitdiffabout
path: root/src/meta1-gram.y
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-15 10:51:03 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2011-05-15 11:05:39 (GMT)
commita0826b4c7cd66c4862d9b61bb7e14d73fcba28f6 (patch) (side-by-side diff)
tree71762fca263967e5803ce803b0a0aa94555e125d /src/meta1-gram.y
parentfd64fa62bc68d8c2e0d693033e874fcc1f023544 (diff)
downloadgrecs-a0826b4c7cd66c4862d9b61bb7e14d73fcba28f6.tar.gz
grecs-a0826b4c7cd66c4862d9b61bb7e14d73fcba28f6.tar.bz2
Provide a framework for multiple parsers. Implement meta1 parser.
* Makefile.am (EXTRA_DIST): Add build-aux/yyrename * am/grecs.m4: New options: parser-meta1 and all-parsers * src/.gitignore: Update. * src/Make.am [GRECS_COND_META1_PARSER]: Set GRECS_PARSER_META1 and GRECS_EXTRA_META1 (GRECS_SRC): Add new files. (EXTRA_DIST): Add GRECS_EXTRA_META1. (LEXCOMPILE,YACCCOMPILE): Redefine * src/grecs-gram.y: Don't include yygrecs.h (grecs_vasprintf,grecs_asprintf): Move to a separate file. (grecs_parse): Rename to grecs_grecs_parser. Actual grecs_parse is defined in parser.c (grecs_gram_trace): Move to parser.c * src/grecs-lex.l: Don't include yygrecs.h Use line_acc functions. * src/grecs.h (grecs_trace_flags): New extern. (GRECS_TRACE_GRAM, GRECS_TRACE_LEX): New flags. (grecs_lex_begin): Change signature. (grecs_grecs_parser,grecs_meta1_parser): New protos. (grecs_line_acc_create) (grecs_line_acc_free,grecs_line_acc_grow_char) (grecs_line_acc_grow_char_unescape) (grecs_line_acc_grow) (grecs_line_acc_grow_unescape_last): New protos. (GRECS_TXTACC_BUFSIZE): New const (grecs_txtacc_create,grecs_txtacc_free) (grecs_txtacc_grow,grecs_txtacc_finish) (grecs_txtacc_free_string): New protos. (grecs_value_match): New proto. * src/wordsplit.c (quote_transtab): Translate \" * src/yygrecs.h: Remove. * src/yytrans: New file. * build-aux/yyrename: New file. * src/asprintf.c: New file. * src/lineacc.c: New file. * src/meta1-gram.y: New file. * src/meta1-lex.l: New file. * src/parser.c: New file. * src/txtacc.c: New file. * doc/grecs_parse.3: Update. * doc/GRECS_SETUP.3: Update.
Diffstat (limited to 'src/meta1-gram.y') (more/less context) (ignore whitespace changes)
-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
--- a/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.