summaryrefslogtreecommitdiffabout
path: root/lib
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-22 13:15:48 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2012-09-22 13:30:07 (GMT)
commit0666fc3caae8e2db660d781e43bee2258bf06a00 (patch) (unidiff)
tree97380903872520efa3b2bf659465e63f2cf51a2a /lib
parent7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee (diff)
downloadeclat-0666fc3caae8e2db660d781e43bee2258bf06a00.tar.gz
eclat-0666fc3caae8e2db660d781e43bee2258bf06a00.tar.bz2
Introduce output formatting language
* configure.ac: Check for lex and yacc. * lib/diag.c: New file (moved from ../src with edits) * lib/forlan.c: New file. * lib/forlan.h: New file. * lib/forlangrm.y: New file. * lib/forlanlex.l: New file. * lib/.gitignore: Add new files. * lib/Makefile.am: Add new file. * lib/libeclat.h: Add diagnostics-related stuff. * src/Makefile.am (eclat_SOURCES): Remove diag.c * src/cmdline.opt (set_program_name): Move to ../lib/diag.c * src/diag.c: Remove (see above). * src/config.c: Reflect changes to the diagnostics subsystem. * src/eclat.c: Likewise. * src/eclat.h: Remove diagnostics-related stuff. It lives in libeclat.h from now on. * src/error.c: Remove. * tests/forlan01.at: New testcase. * tests/testsuite.at: Include forlan01.at * tests/tforlan.c: New file. * tests/.gitignore: Add new files. * tests/Makefile.am: Add new files.
Diffstat (limited to 'lib') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/.gitignore4
-rw-r--r--lib/Makefile.am15
-rw-r--r--lib/diag.c181
-rw-r--r--lib/forlan.c258
-rw-r--r--lib/forlan.h123
-rw-r--r--lib/forlangrm.y237
-rw-r--r--lib/forlanlex.l137
-rw-r--r--lib/libeclat.h33
8 files changed, 988 insertions, 0 deletions
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..e0d9b22
--- a/dev/null
+++ b/lib/.gitignore
@@ -0,0 +1,4 @@
1forlangrm.c
2forlangrm.h
3forlangrm.output
4forlanlex.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2c1d3a8..50b28a5 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -18,6 +18,12 @@ noinst_LIBRARIES=libeclat.a
18 18
19libeclat_a_SOURCES=\ 19libeclat_a_SOURCES=\
20 base64.c\ 20 base64.c\
21 diag.c\
22 forlan.c\
23 forlan.h\
24 forlangrm.h\
25 forlangrm.y\
26 forlanlex.l\
21 hmac_sha1.c\ 27 hmac_sha1.c\
22 libeclat.h\ 28 libeclat.h\
23 q2url.c\ 29 q2url.c\
@@ -33,3 +39,12 @@ libeclat_a_SOURCES=\
33 39
34AM_LDFLAGS = $(CURL_LIBS) 40AM_LDFLAGS = $(CURL_LIBS)
35INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS) 41INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS)
42
43forlanlex.c: forlangrm.h
44forlangrm.c forlangrm.h: forlangrm.y
45
46AM_YFLAGS=-tdv
47AM_LFLAGS=-dvp
48
49
50
diff --git a/lib/diag.c b/lib/diag.c
new file mode 100644
index 0000000..d061e9e
--- a/dev/null
+++ b/lib/diag.c
@@ -0,0 +1,181 @@
1/* This file is part of Eclat.
2 Copyright (C) 2012 Sergey Poznyakoff.
3
4 Eclat is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 Eclat is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "libeclat.h"
18#include <string.h>
19#include <sysexits.h>
20
21const char *program_name;
22struct debug_category debug_category[LIBECLAT_DBG_MAX];
23int debug_avail;
24
25void
26set_program_name(const char *arg)
27{
28 program_name = strrchr(arg, '/');
29 if (!program_name)
30 program_name = arg;
31 else
32 program_name++;
33}
34
35void
36vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt,
37 va_list ap)
38{
39 if (program_name)
40 fprintf(stderr, "%s: ", program_name);
41
42 if (locus) {
43 size_t size = 0;
44
45 if (locus->beg.col == 0)
46 fprintf(stderr, "%s:%u",
47 locus->beg.file,
48 locus->beg.line);
49 else if (strcmp(locus->beg.file, locus->end.file))
50 fprintf(stderr, "%s:%u.%u-%s:%u.%u",
51 locus->beg.file,
52 locus->beg.line, locus->beg.col,
53 locus->end.file,
54 locus->end.line, locus->end.col);
55 else if (locus->beg.line != locus->end.line)
56 fprintf(stderr, "%s:%u.%u-%u.%u",
57 locus->beg.file,
58 locus->beg.line, locus->beg.col,
59 locus->end.line, locus->end.col);
60 else
61 fprintf(stderr, "%s:%u.%u-%u",
62 locus->beg.file,
63 locus->beg.line, locus->beg.col,
64 locus->end.col);
65 fprintf(stderr, ": ");
66 }
67
68 if (qual)
69 fprintf(stderr, "%s: ", qual);
70 vfprintf(stderr, fmt, ap);
71 fputc('\n', stderr);
72}
73
74void
75diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...)
76{
77 va_list ap;
78
79 va_start(ap, fmt);
80 vdiag(locus, qual, fmt, ap);
81 va_end(ap);
82 }
83
84void
85die(int status, const char *fmt, ...)
86{
87 va_list ap;
88
89 va_start(ap, fmt);
90 vdiag(NULL, NULL, fmt, ap);
91 va_end(ap);
92 exit(status);
93}
94
95void
96err(const char *fmt, ...)
97{
98 va_list ap;
99
100 va_start(ap, fmt);
101 vdiag(NULL, NULL, fmt, ap);
102 va_end(ap);
103}
104
105void
106warn(const char *fmt, ...)
107{
108 va_list ap;
109
110 va_start(ap, fmt);
111 vdiag(NULL, "warning", fmt, ap);
112 va_end(ap);
113}
114
115void
116debug_printf(const char *fmt, ...)
117{
118 va_list ap;
119
120 va_start(ap, fmt);
121 vdiag(NULL, "debug", fmt, ap);
122 va_end(ap);
123 }
124
125static struct debug_category *
126find_category(const char *arg, size_t len)
127{
128 struct debug_category *dp;
129
130 for (dp = debug_category; dp < debug_category + debug_avail; dp++)
131 if (dp->length == len && memcmp(dp->name, arg, len) == 0)
132 return dp;
133 return NULL;
134}
135
136int
137parse_debug_level(const char *arg)
138{
139 unsigned long lev;
140 char *p;
141 size_t len = strcspn(arg, ".");
142 struct debug_category *dp;
143
144 if (arg[len] == 0) {
145 lev = strtoul(arg, &p, 10);
146 if (*p)
147 return -1;
148 for (dp = debug_category; dp < debug_category + debug_avail;
149 dp++)
150 dp->level = lev;
151 return 0;
152 }
153
154 dp = find_category(arg, len);
155 if (!dp)
156 return -1;
157
158 p = (char*) arg + len;
159 if (*p == 0)
160 lev = 100;
161 else if (*p != '.')
162 return -1;
163 else {
164 lev = strtoul(p + 1, &p, 10);
165 if (*p)
166 return -1;
167 }
168 dp->level = lev;
169 return 0;
170}
171
172int
173debug_register(char *name)
174{
175 if (debug_avail >= LIBECLAT_DBG_MAX)
176 die(EX_SOFTWARE, "no more debug slots available");
177 debug_category[debug_avail].name = grecs_strdup(name);
178 debug_category[debug_avail].length = strlen(name);
179 debug_category[debug_avail].level = 0;
180 return debug_avail++;
181}
diff --git a/lib/forlan.c b/lib/forlan.c
new file mode 100644
index 0000000..0854d08
--- a/dev/null
+++ b/lib/forlan.c
@@ -0,0 +1,258 @@
1/* This file is part of Eclat.
2 Copyright (C) 2012 Sergey Poznyakoff.
3
4 Eclat is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 Eclat is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "libeclat.h"
18#include "grecs.h"
19#include "forlan.h"
20
21int forlan_dbg = -1;
22
23void
24forlan_init()
25{
26 forlan_dbg = debug_register("forlan");
27}
28
29union forlan_node *
30forlan_node_create(enum forlan_type type)
31{
32 union forlan_node *p = grecs_zalloc(sizeof(*p));
33 p->type = type;
34 return p;
35}
36
37static void f_dump_node(FILE *fp, union forlan_node *p, int *num, int lev);
38
39
40static void
41free_type_null(union forlan_node *p)
42{
43 warn("freeing undefined forlan_node");
44}
45
46void
47dump_null(FILE *fp, union forlan_node *p, int *num, int lev)
48{
49 fprintf(fp, "[undefined node]\n");
50}
51
52static void
53free_type_comp(union forlan_node *p)
54{
55 forlan_node_free(p->comp.node);
56}
57void
58dump_comp(FILE *fp, union forlan_node *p, int *num, int lev)
59{
60 fprintf(fp, "COMP");
61 if (p->comp.abs)
62 fprintf(fp, " ABS");
63 fputc('\n', fp);
64 forlan_dump_node(fp, p->comp.node, num, lev + 1);
65}
66
67static void
68free_type_test(union forlan_node *p)
69{
70 free(p->test.comp);
71 free(p->test.value);
72}
73void
74dump_test(FILE *fp, union forlan_node *p, int *num, int lev)
75{
76 fprintf(fp, "TEST: %s[%s]\n", p->test.comp, p->test.value);
77}
78
79static void
80free_type_func(union forlan_node *p)
81{
82 grecs_list_free(p->func.args);
83}
84void
85dump_func(FILE *fp, union forlan_node *p, int *num, int lev)
86{
87 struct grecs_list_entry *ep;
88 fprintf(fp, "CALL: %s\n", p->func.fp);
89 if (p->func.args)
90 for (ep = p->func.args->head; ep; ep = ep->next)
91 forlan_dump_node(fp, ep->data, num, lev + 1);
92 }
93
94static void
95free_type_cond(union forlan_node *p)
96{
97 forlan_node_free((union forlan_node *)p->cond.expr);
98 forlan_node_free(p->cond.iftrue);
99 forlan_node_free(p->cond.iffalse);
100}
101void
102dump_cond(FILE *fp, union forlan_node *p, int *num, int lev)
103{
104 int n = *num;
105 fprintf(fp, "COND\n");
106 forlan_dump_node(fp, p->cond.expr, num, lev + 1);
107 fprintf(fp, "%04d: %*.*sIFTRUE %04d\n", ++*num, lev, lev, "", n);
108 forlan_dump_node(fp, p->cond.iftrue, num, lev + 1);
109 fprintf(fp, "%04d: %*.*sIFFALSE %04d\n", ++*num, lev, lev, "", n);
110 forlan_dump_node(fp, p->cond.iffalse, num, lev + 1);
111}
112
113static void
114free_type_stmt(union forlan_node *p)
115{
116 forlan_node_free(p->stmt.stmt);
117 forlan_node_free(p->stmt.next);
118}
119void
120dump_stmt(FILE *fp, union forlan_node *p, int *num, int lev)
121{
122 f_dump_node(fp, p->stmt.stmt, num, lev);
123 forlan_dump_node(fp, p->stmt.next, num, lev);
124}
125
126static void
127free_type_lit(union forlan_node *p)
128{
129 free(p->lit.string);
130}
131void
132dump_lit(FILE *fp, union forlan_node *p, int *num, int lev)
133{
134 fprintf(fp, "LIT: \"%s\"\n", p->lit.string);
135}
136
137static void
138free_type_expr(union forlan_node *p)
139{
140 forlan_node_free(p->expr.arg[0]);
141 forlan_node_free(p->expr.arg[1]);
142}
143void
144dump_expr(FILE *fp, union forlan_node *p, int *num, int lev)
145{
146 static char *opstr[] = { "NODE", "AND", "OR", "NOT" };
147
148 fprintf(fp, "%s\n", opstr[p->expr.opcode]);
149 forlan_dump_node(fp, p->expr.arg[0], num, lev + 1);
150 if (p->expr.arg[1])
151 forlan_dump_node(fp, p->expr.arg[1], num, lev + 1);
152}
153
154static void
155free_type_last(union forlan_node *p)
156{
157}
158void
159dump_last(FILE *fp, union forlan_node *p, int *num, int lev)
160{
161 fprintf(fp, "LAST\n");
162}
163
164struct forlan_node_method {
165 void (*f_free)(union forlan_node *);
166 void (*f_dump)(FILE *fp, union forlan_node *node, int *num, int lev);
167};
168
169static struct forlan_node_method f_tab[] = {
170 free_type_null, dump_null, /* Unknown/unset type */
171 free_type_comp, dump_comp, /* A path component */
172 free_type_test, dump_test, /* Value test (f[X]) */
173 free_type_func, dump_func, /* Function call */
174 free_type_cond, dump_cond, /* Conditional */
175 free_type_stmt, dump_stmt, /* Statement */
176 free_type_lit, dump_lit, /* Literal */
177 free_type_expr, dump_expr, /* Boolean expression */
178 free_type_last, dump_last, /* "last" */
179};
180
181void
182forlan_node_free(union forlan_node *p)
183{
184 if (!p)
185 return;
186 if (p->type > sizeof(f_tab) / sizeof(f_tab[0]))
187 abort();
188 if (f_tab[p->type].f_free)
189 f_tab[p->type].f_free(p);
190 free(p);
191}
192
193static void
194stmt_list_free_entry(void *p)
195{
196 forlan_node_free(p);
197}
198
199struct grecs_list *
200forlan_stmt_list()
201{
202 struct grecs_list *lp;
203
204 lp = grecs_list_create();
205 lp->free_entry = stmt_list_free_entry;
206 return lp;
207}
208
209union forlan_node *
210forlan_stmt_from_list(struct grecs_list *list)
211{
212 union forlan_node **tail = NULL, *ret = NULL;
213 struct grecs_list_entry *ep;
214
215 for (ep = list->head; ep; ep = ep->next) {
216 union forlan_node *sp = forlan_node_create(forlan_type_stmt);
217 sp->stmt.stmt = ep->data;
218 if (tail)
219 *tail = sp;
220 else
221 ret = sp;
222 tail = &sp->stmt.next;
223 }
224 list->free_entry = NULL;
225 grecs_list_free(list);
226 return ret;
227}
228
229static void
230f_dump_node(FILE *fp, union forlan_node *p, int *num, int lev)
231{
232 if (p) {
233 if (p->type > sizeof(f_tab) / sizeof(f_tab[0]))
234 abort();
235 if (f_tab[p->type].f_dump)
236 f_tab[p->type].f_dump(fp, p, num, lev);
237 else
238 fprintf(fp, "type %d", p->type);
239 } else
240 fprintf(fp, "NULL");
241}
242
243void
244forlan_dump_node(FILE *fp, union forlan_node *p, int *num, int lev)
245{
246 if (!p)
247 return;
248 ++*num;
249 fprintf(fp, "%04d: %*.*s", *num, lev, lev, "");
250 f_dump_node(fp, p, num, lev);
251}
252
253void
254forlan_dump_tree(FILE *fp, union forlan_node *node)
255{
256 int n = 0;
257 forlan_dump_node(fp, node, &n, 0);
258}
diff --git a/lib/forlan.h b/lib/forlan.h
new file mode 100644
index 0000000..4dadc70
--- a/dev/null
+++ b/lib/forlan.h
@@ -0,0 +1,123 @@
1/* This file is part of Eclat.
2 Copyright (C) 2012 Sergey Poznyakoff.
3
4 Eclat is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 Eclat is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
16
17#define FORLAN_DBG_LEX 3
18#define FORLAN_DBG_GRAM 2
19#define FORLAN_DBG_EVAL 1
20
21extern int forlan_dbg;
22
23void forlan_init();
24void forlan_lex_begin(const char *input, size_t length,
25 struct grecs_locus_point *pt);
26void forlan_lex_end(void);
27int forlan_parse(const char *input, size_t length,
28 struct grecs_locus_point *pt);
29
30union forlan_node; /* Declared below */
31
32enum forlan_type {
33 forlan_type_null, /* Unknown/unset type */
34 forlan_type_comp, /* A path component */
35 forlan_type_test,/* Value test (f[X]) */
36 forlan_type_func,/* Function call */
37 forlan_type_cond,/* Conditional */
38 forlan_type_stmt,/* Statement */
39 forlan_type_lit,/* Literal */
40 forlan_type_expr, /* Boolean expression */
41 forlan_type_last /* Return last evaluated grecs_node */
42};
43
44/* A path component */
45struct forlan_node_comp {
46 enum forlan_type type;
47 int abs;
48 union forlan_node *node;
49};
50
51/* Path test: .path.comp[value] */
52struct forlan_node_test {
53 enum forlan_type type;
54 char *comp;
55 char *value;
56};
57
58/* Function call */
59struct forlan_node_func {
60 enum forlan_type type;
61 void *fp; /* FIXME: replace with typedef */
62 struct grecs_list *args; /* Arguments are struct forlan_node * */
63};
64
65/* Conditional */
66struct forlan_node_cond {
67 enum forlan_type type;
68 union forlan_node *expr; /* Controlling expression */
69 union forlan_node *iftrue; /* Run this if expr yields true */
70 union forlan_node *iffalse; /* Run this if expr yields false */
71};
72
73/* Statement or statement list */
74struct forlan_node_stmt {
75 enum forlan_type type;
76 union forlan_node *stmt;
77 union forlan_node *next;
78};
79
80/* Literal string */
81struct forlan_node_lit {
82 enum forlan_type type;
83 char *string;
84};
85
86/* Boolean opcodes */
87enum forlan_opcode {
88 forlan_opcode_node, /* Evaluate node, set 'last' */
89 forlan_opcode_and, /* Boolean AND */
90 forlan_opcode_or, /* Boolean OR */
91 forlan_opcode_not /* Boolean NOT */
92};
93
94/* Boolean expression */
95struct forlan_node_expr {
96 enum forlan_type type;
97 enum forlan_opcode opcode;
98 union forlan_node *arg[2];
99};
100
101/* Now get all this together */
102union forlan_node {
103 enum forlan_type type;
104 struct forlan_node_comp comp; /* A path component */
105 struct forlan_node_test test; /* Value test (f[X]) */
106 struct forlan_node_func func; /* Function call */
107 struct forlan_node_cond cond; /* Conditional */
108 struct forlan_node_stmt stmt; /* Statement */
109 struct forlan_node_lit lit; /* Literal */
110 struct forlan_node_expr expr; /* Boolean expression */
111 /* forlan_type_last needs no additional data */
112};
113
114union forlan_node *forlan_node_create(enum forlan_type type);
115void forlan_node_free(union forlan_node *);
116struct grecs_list *forlan_stmt_list(void);
117struct grecs_list *forlan_complist(void);
118union forlan_node *forlan_stmt_from_list(struct grecs_list *list);
119
120extern union forlan_node *forlan_parse_tree;
121
122void forlan_dump_node(FILE *fp, union forlan_node *p, int *num, int lev);
123void forlan_dump_tree(FILE *fp, union forlan_node *node);
diff --git a/lib/forlangrm.y b/lib/forlangrm.y
new file mode 100644
index 0000000..1b7781d
--- a/dev/null
+++ b/lib/forlangrm.y
@@ -0,0 +1,237 @@
1%{
2/* This file is part of Eclat.
3 Copyright (C) 2012 Sergey Poznyakoff.
4
5 Eclat is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 Eclat is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "libeclat.h"
19#include <grecs.h>
20#include <grecs-locus.h>
21#include "forlangrm.h"
22#include "forlan.h"
23
24static int yyerror(char *);
25union forlan_node *forlan_parse_tree;
26%}
27%error-verbose
28%locations
29
30%union {
31 char *string;
32 union forlan_node *node;
33 struct grecs_list *list;
34};
35
36%token <string> STRING IDENT
37%token LAST IF ELSE
38
39%left OR
40%left AND
41%left NOT
42
43%type <node> stmt stmt_cond stmt_expr stmt_blk cond bool node comp funcall arg
44%type <list> stmtlist complist arglist
45%type <string> string
46
47%%
48input : stmtlist
49 {
50 forlan_parse_tree = forlan_stmt_from_list($1);
51 }
52 ;
53
54stmtlist : stmt
55 {
56 $$ = forlan_stmt_list();
57 grecs_list_append($$, $1);
58 }
59 | stmtlist stmt
60 {
61 grecs_list_append($1, $2);
62 $$ = $1;
63 }
64 ;
65
66stmt : stmt_cond
67 | stmt_expr
68 | stmt_blk
69 ;
70
71stmt_blk : '{' stmtlist '}'
72 {
73 $$ = forlan_stmt_from_list($2);
74 }
75 ;
76
77stmt_cond : IF cond stmt
78 {
79 $$ = forlan_node_create(forlan_type_cond);
80 $$->cond.expr = $2;
81 $$->cond.iftrue = $3;
82 $$->cond.iffalse = NULL;
83 }
84 | IF cond stmt ELSE stmt
85 {
86 $$ = forlan_node_create(forlan_type_cond);
87 $$->cond.expr = $2;
88 $$->cond.iftrue = $3;
89 $$->cond.iffalse = $5;
90 }
91 ;
92
93cond : bool
94 ;
95
96bool : node
97 {
98 $$ = forlan_node_create(forlan_type_expr);
99 $$->expr.opcode = forlan_opcode_node;
100 $$->expr.arg[0] = $1;
101 }
102 | bool AND bool
103 {
104 $$ = forlan_node_create(forlan_type_expr);
105 $$->expr.opcode = forlan_opcode_and;
106 $$->expr.arg[0] = $1;
107 $$->expr.arg[1] = $3;
108 }
109 | bool OR bool
110 {
111 $$ = forlan_node_create(forlan_type_expr);
112 $$->expr.opcode = forlan_opcode_or;
113 $$->expr.arg[0] = $1;
114 $$->expr.arg[1] = $3;
115 }
116 | NOT bool
117 {
118 $$ = forlan_node_create(forlan_type_expr);
119 $$->expr.opcode = forlan_opcode_not;
120 $$->expr.arg[0] = $2;
121 }
122 | '(' bool ')'
123 {
124 $$ = $2;
125 }
126 ;
127
128node : complist
129 {
130 $$ = forlan_node_create(forlan_type_comp);
131 $$->comp.abs = 0;
132 $$->comp.node = forlan_stmt_from_list($1);
133 }
134 | '.' complist
135 {
136 $$ = forlan_node_create(forlan_type_comp);
137 $$->comp.abs = 1;
138 $$->comp.node = forlan_stmt_from_list($2);
139 }
140 | LAST
141 {
142 $$ = forlan_node_create(forlan_type_last);
143 }
144 ;
145
146complist : comp
147 {
148 $$ = forlan_stmt_list();
149 grecs_list_append($$, $1);
150 }
151 | complist '.' comp
152 {
153 grecs_list_append($1, $3);
154 $$ = $1;
155 }
156 ;
157
158comp : IDENT
159 {
160 $$ = forlan_node_create(forlan_type_lit);
161 $$->lit.string = $1;
162 }
163 | IDENT '[' string ']'
164 {
165 $$ = forlan_node_create(forlan_type_test);
166 $$->test.comp = $1;
167 $$->test.value = $3;
168 }
169 | funcall
170 ;
171
172string : IDENT
173 | STRING
174 ;
175
176funcall : IDENT '(' ')'
177 {
178 $$ = forlan_node_create(forlan_type_func);
179 $$->func.fp = $1; //FIXME
180 $$->func.args = NULL;
181 }
182 | IDENT '(' arglist ')'
183 {
184 $$ = forlan_node_create(forlan_type_func);
185 $$->func.fp = $1; //FIXME
186 $$->func.args = $3;
187 }
188 ;
189
190arglist : arg
191 {
192 $$ = forlan_stmt_list();
193 grecs_list_append($$, $1);
194 }
195 | arglist ',' arg
196 {
197 grecs_list_append($1, $3);
198 $$ = $1;
199 }
200 ;
201
202arg : node
203 | STRING
204 {
205 $$ = forlan_node_create(forlan_type_lit);
206 $$->lit.string = $1;
207 }
208 ;
209
210stmt_expr : funcall ';'
211 ;
212%%
213static int
214yyerror(char *s)
215{
216 grecs_error(&yylloc, 0, "%s", s);
217 return 0;
218}
219
220int
221forlan_parser()
222{
223 yydebug = debug_level(forlan_dbg) >= FORLAN_DBG_GRAM;
224 return yyparse();
225}
226
227int
228forlan_parse(const char *input, size_t length, struct grecs_locus_point *pt)
229{
230 int rc;
231 forlan_lex_begin(input, length, pt);
232 rc = forlan_parser();
233 forlan_lex_end();
234 return rc;
235}
236
237
diff --git a/lib/forlanlex.l b/lib/forlanlex.l
new file mode 100644
index 0000000..99966ed
--- a/dev/null
+++ b/lib/forlanlex.l
@@ -0,0 +1,137 @@
1%{
2/* This file is part of Eclat.
3 Copyright (C) 2012 Sergey Poznyakoff.
4
5 Eclat is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 Eclat is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "libeclat.h"
19#include <grecs.h>
20#include <grecs-locus.h>
21#include "forlangrm.h"
22#include "forlan.h"
23
24static const char *forlan_input_base;
25static size_t forlan_input_len;
26static size_t forlan_input_pos;
27
28#undef YY_INPUT
29 #define YY_INPUT(buf,result,max_size) \
30 do { \
31 size_t __s = forlan_input_len - forlan_input_pos; \
32 if (__s > max_size) \
33 __s = max_size; \
34 if (__s > 0) { \
35 memcpy(buf, forlan_input_base, __s); \
36 forlan_input_pos += __s; \
37 } \
38 result = __s; \
39 } while(0)
40
41 #define YY_USER_ACTION do { \
42 if (YYSTATE == 0) { \
43 yylloc.beg = grecs_current_locus_point; \
44 yylloc.beg.col++; \
45 } \
46 grecs_current_locus_point.col += yyleng; \
47 yylloc.end = grecs_current_locus_point; \
48 } while (0);
49
50static int yywrap(void);
51
52%}
53
54WS [ \t\f][ \t\f]*
55IDC [a-zA-Z_0-9-]
56%x COMMENT ML STR
57%%
58 /* Comments */
59"/*" BEGIN(COMMENT);
60<COMMENT>[^*\n]* /* eat anything that's not a '*' */
61<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
62<COMMENT>\n grecs_locus_point_advance_line(grecs_current_locus_point);
63<COMMENT>"*"+"/" BEGIN(INITIAL);
64"//".* ;
65 /* Keywords */
66if return IF;
67else return ELSE;
68last return LAST;
69! return NOT;
70"&&" return AND;
71"||" return OR;
72{IDC}{IDC}* { grecs_line_begin();
73 grecs_line_add(yytext, yyleng);
74 yylval.string = grecs_line_finish();
75 return IDENT; }
76 /* Quoted strings */
77\"[^\\"\n]*\" { grecs_line_begin();
78 grecs_line_add(yytext + 1, yyleng - 2);
79 yylval.string = grecs_line_finish();
80 return STRING; }
81\"[^\\"\n]*\\\n { BEGIN(STR);
82 grecs_line_begin();
83 grecs_line_acc_grow_unescape_last(yytext + 1,
84 yyleng - 1);
85 grecs_locus_point_advance_line(grecs_current_locus_point); }
86\"[^\\"\n]*\\. { BEGIN(STR);
87 grecs_line_begin();
88 grecs_line_acc_grow_unescape_last(yytext + 1,
89 yyleng - 1); }
90<STR>\"[^\\"\n]*\\\n { grecs_line_acc_grow_unescape_last(yytext, yyleng);
91 grecs_locus_point_advance_line(grecs_current_locus_point); }
92<STR>[^\\"\n]*\\. { grecs_line_acc_grow_unescape_last(yytext, yyleng); }
93<STR>[^\\"\n]*\" { BEGIN(INITIAL);
94 if (yyleng > 1)
95 grecs_line_add(yytext, yyleng - 1);
96 yylval.string = grecs_line_finish();
97 return STRING; }
98 /* Other tokens */
99{WS} ;
100\n { grecs_locus_point_advance_line(grecs_current_locus_point); }
101[.,;{}()\[\]] return yytext[0];
102. { if (isascii(yytext[0]) && isprint(yytext[0]))
103 grecs_error(&yylloc, 0,
104 _("stray character %c"), yytext[0]);
105 else
106 grecs_error(&yylloc, 0,
107 _("stray character \\%03o"),
108 (unsigned char) yytext[0]); }
109%%
110
111static int
112yywrap()
113{
114 return 1;
115}
116
117void
118forlan_lex_begin(const char *input, size_t length,
119 struct grecs_locus_point *pt)
120{
121 forlan_input_base = input;
122 forlan_input_len = length;
123 grecs_current_locus_point = *pt;
124 yy_flex_debug = debug_level(forlan_dbg) >= FORLAN_DBG_LEX;
125 grecs_line_acc_create();
126}
127
128void
129forlan_lex_end()
130{
131 grecs_line_acc_free();
132}
133
134
135
136
137
diff --git a/lib/libeclat.h b/lib/libeclat.h
index 670c51b..5f37cc9 100644
--- a/lib/libeclat.h
+++ b/lib/libeclat.h
@@ -18,6 +18,39 @@
18#include <expat.h> 18#include <expat.h>
19#include "grecs.h" 19#include "grecs.h"
20 20
21extern const char *program_name;
22
23struct debug_category {
24 const char *name;
25 size_t length;
26 int level;
27};
28
29extern struct debug_category debug_category[];
30#define LIBECLAT_DBG_MAX 64
31
32 #define debug_level(cat) ((cat >= 0 && cat < LIBECLAT_DBG_MAX) ?\
33 debug_category[cat].level : 0)
34 #define debug(cat, lev, s) \
35 do { \
36 if (debug_level(cat) >= (lev)) \
37 debug_printf s; \
38 } while(0)
39
40void set_program_name(const char *arg);
41
42void die(int status, const char *fmt, ...);
43void vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt,
44 va_list ap);
45void diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...);
46void err(const char *fmt, ...);
47void warn(const char *fmt, ...);
48void debug_printf(const char *fmt, ...);
49
50int parse_debug_level(const char *arg);
51int debug_register(char *name);
52
53
21void hmac_sha1(const void *text, size_t textlen, 54void hmac_sha1(const void *text, size_t textlen,
22 const void *key, size_t keylen, 55 const void *key, size_t keylen,
23 void *digest); 56 void *digest);

Return to:

Send suggestions and report system problems to the System administrator.