aboutsummaryrefslogtreecommitdiff
path: root/src/argot-gram.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/argot-gram.y')
-rw-r--r--src/argot-gram.y274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/argot-gram.y b/src/argot-gram.y
new file mode 100644
index 0000000..b92794c
--- /dev/null
+++ b/src/argot-gram.y
@@ -0,0 +1,274 @@
+%{
+/* argot - Gray's Extensible Configuration System
+ Copyright (C) 2007-2016 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 <argot.h>
+#include <argot-gram.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+int yylex(void);
+int yyerror(char const *s);
+
+static struct argot_node *parse_tree;
+%}
+
+%error-verbose
+%locations
+
+%union {
+ char *string;
+ argot_value_t svalue, *pvalue;
+ struct argot_list *list;
+ struct argot_node *node;
+ argot_locus_t locus;
+ struct { struct argot_node *head, *tail; } node_list;
+}
+
+%token <string> STRING QSTRING MSTRING IDENT
+%type <string> string slist
+%type <list> slist0
+%type <svalue> value
+%type <pvalue> vallist tag
+%type <list> values list vlist
+%type <node> stmt simple block maybe_stmtlist
+%type <node_list> stmtlist
+
+%%
+
+input : maybe_stmtlist
+ {
+ parse_tree = argot_node_create(argot_node_root, &@1);
+ parse_tree->v.texttab = argot_text_table();
+ argot_node_bind(parse_tree, $1, 1);
+ }
+ ;
+
+maybe_stmtlist:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | stmtlist
+ {
+ $$ = $1.head;
+ }
+ ;
+
+stmtlist: stmt
+ {
+ $$.head = $$.tail = $1;
+ }
+ | stmtlist stmt
+ {
+ argot_node_bind($1.tail, $2, 0);
+ }
+ ;
+
+stmt : simple
+ | block
+ ;
+
+simple : IDENT vallist ';'
+ {
+ $$ = argot_node_create_points(argot_node_stmt,
+ @1.beg, @2.end);
+ $$->ident = $1;
+ $$->idloc = @1;
+ $$->v.value = $2;
+ }
+ | IDENT ';'
+ {
+ $$ = argot_node_create(argot_node_stmt, &@1);
+ $$->ident = $1;
+ $$->idloc = @1;
+ $$->v.value = NULL;
+ }
+ ;
+
+block : IDENT tag '{' stmtlist '}' opt_sc
+ {
+ $$ = argot_node_create_points(argot_node_block,
+ @1.beg, @5.end);
+ $$->ident = $1;
+ $$->idloc = @1;
+ $$->v.value = $2;
+ argot_node_bind($$, $4.head, 1);
+ }
+ ;
+
+tag : /* empty */
+ {
+ $$ = NULL;
+ }
+ | vallist
+ ;
+
+vallist : vlist
+ {
+ size_t n;
+
+ if ((n = argot_list_size($1)) == 1) {
+ $$ = argot_list_index($1, 0);
+ } else {
+ size_t i;
+ struct argot_list_entry *ep;
+
+ $$ = argot_malloc(sizeof($$[0]));
+ $$->type = ARGOT_TYPE_ARRAY;
+ $$->locus = @1;
+ $$->v.arg.c = n;
+ $$->v.arg.v = argot_calloc(n,
+ sizeof($$->v.arg.v[0]));
+ for (i = 0, ep = $1->head; ep; i++, ep = ep->next)
+ $$->v.arg.v[i] = ep->data;
+ }
+ $1->free_entry = NULL;
+ argot_list_free($1);
+ }
+ ;
+
+vlist : value
+ {
+ $$ = argot_value_list_create();
+ argot_list_append($$, argot_value_ptr_from_static(&$1));
+ }
+ | vlist value
+ {
+ argot_list_append($1, argot_value_ptr_from_static(&$2));
+ }
+ ;
+
+value : string
+ {
+ $$.type = ARGOT_TYPE_STRING;
+ $$.locus = @1;
+ $$.v.string = $1;
+ }
+ | list
+ {
+ $$.type = ARGOT_TYPE_LIST;
+ $$.locus = @1;
+ $$.v.list = $1;
+ }
+ | MSTRING
+ {
+ $$.type = ARGOT_TYPE_STRING;
+ $$.locus = @1;
+ $$.v.string = $1;
+ }
+ ;
+
+string : STRING
+ | IDENT
+ | slist
+ ;
+
+slist : slist0
+ {
+ struct argot_list_entry *ep;
+
+ argot_line_begin();
+ for (ep = $1->head; ep; ep = ep->next) {
+ argot_line_add(ep->data, strlen(ep->data));
+ free(ep->data);
+ ep->data = NULL;
+ }
+ $$ = argot_line_finish();
+ argot_list_free($1);
+ }
+ ;
+
+slist0 : QSTRING
+ {
+ $$ = argot_list_create();
+ argot_list_append($$, $1);
+ }
+ | slist0 QSTRING
+ {
+ argot_list_append($1, $2);
+ $$ = $1;
+ }
+ ;
+
+list : '(' ')'
+ {
+ $$ = NULL;
+ }
+ | '(' values ')'
+ {
+ $$ = $2;
+ }
+ | '(' values ',' ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+values : value
+ {
+ $$ = argot_value_list_create();
+ argot_list_append($$, argot_value_ptr_from_static(&$1));
+ }
+ | values ',' value
+ {
+ argot_list_append($1, argot_value_ptr_from_static(&$3));
+ $$ = $1;
+ }
+ ;
+
+opt_sc : /* empty */
+ | ';'
+ ;
+
+%%
+
+int
+yyerror(char const *s)
+{
+ argot_error(&yylloc, 0, "%s", s);
+ return 0;
+}
+
+struct argot_node *
+argot_argot_parser(const char *name, int traceflags)
+{
+ int rc;
+ if (argot_lex_begin(name, traceflags & ARGOT_TRACE_LEX))
+ return NULL;
+ yydebug = traceflags & ARGOT_TRACE_GRAM;
+ parse_tree = NULL;
+ rc = yyparse();
+ if (argot_error_count)
+ rc = 1;
+ argot_lex_end(rc);
+ if (rc) {
+ argot_tree_free(parse_tree);
+ parse_tree = NULL;
+ }
+ return parse_tree;
+}
+
+
+
+
+
+

Return to:

Send suggestions and report system problems to the System administrator.