diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-15 13:51:03 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-15 14:05:39 +0300 |
commit | a0826b4c7cd66c4862d9b61bb7e14d73fcba28f6 (patch) | |
tree | 71762fca263967e5803ce803b0a0aa94555e125d /src/meta1-gram.y | |
parent | fd64fa62bc68d8c2e0d693033e874fcc1f023544 (diff) | |
download | grecs-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')
-rw-r--r-- | src/meta1-gram.y | 217 |
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; +} + |