]> jfr.im git - irc/quakenet/newserv.git/blame_incremental - newsearch/newsearch.y
LUA: port luadb to dbapi2 to drop postgres dependency
[irc/quakenet/newserv.git] / newsearch / newsearch.y
... / ...
CommitLineData
1%{
2#include <stdio.h>
3#include <string.h>
4#include <stdarg.h>
5#include "../lib/stringbuf.h"
6#include "newsearch.h"
7#include "parser.h"
8
9#define YYSTYPE sstring *
10
11int yylex(void);
12extern char *parseStrError;
13extern int parseStrErrorPos;
14
15#define MAXSTACKSIZE 50
16
17typedef struct parserlist {
18 searchASTExpr expr;
19 struct parserlist *next;
20} parserlist;
21
22static int stackpos;
23static parserlist *stack[MAXSTACKSIZE];
24static int stackcount[MAXSTACKSIZE];
25static fnFinder functionfinder;
26static void *fnfarg;
27static parsertree **presult, sresult;
28
29extern int lexerror, lexpos;
30void yystrerror(const char *format, ...);
31void lexreset(void);
32
33void resetparser(fnFinder fnf, void *arg, parsertree **result) {
34 presult = result;
35 *presult = &sresult;
36
37 sresult.exprlist = NULL;
38 sresult.strlist = NULL;
39 sresult.finished = 0;
40
41 functionfinder = fnf;
42 fnfarg = arg;
43
44 stackpos = 0;
45 lexreset();
46}
47
48void yyerror(const char *str) {
49 if(lexerror) {
50 lexerror = 0;
51 yystrerror("lexical error");
52 return;
53 }
54
55 parseStrError = (char *)str;
56 parseStrErrorPos = lexpos;
57}
58
59void yystrerror(const char *format, ...) {
60 va_list va;
61 static char buf[512];
62
63 parse_free(&sresult);
64
65 va_start(va, format);
66 vsnprintf(buf, sizeof(buf), format, va);
67 va_end(va);
68
69 yyerror(buf);
70}
71
72%}
73
74%token LPAREN RPAREN WHITESPACE IDENTIFIER STRING
75
76%%
77invocation: LPAREN function argumentlist RPAREN
78 {
79 sstring *str = $2;
80 int i, count;
81 searchASTExpr *ap, *root;
82 parserlist *pp, *npp;
83 expressionlist *xl;
84 parseFunc pfn;
85
86 stackpos--;
87 count = stackcount[stackpos];
88
89 pfn = functionfinder(str->content, fnfarg);
90 if(!pfn) {
91 yystrerror("unknown function: %s", str->content);
92 YYERROR;
93 }
94 /* if we're at the top of the stack we're the root of the tree */
95 if(stackpos != 0) {
96 /*
97 * we store this function containing its children in the stack list
98 * as there might be functions or other stuff after it, such as:
99 * (fn (fn2) moo moo)
100 */
101 parserlist *rootp = malloc(sizeof(searchASTExpr) + sizeof(parserlist));
102 root = &rootp->expr;
103
104 stackcount[stackpos-1]++;
105 rootp->next = stack[stackpos-1];
106 stack[stackpos-1] = rootp;
107 } else {
108 /* need space for the final result and real root */
109 *presult = malloc(sizeof(parsertree) + sizeof(searchASTExpr));
110
111 memcpy(*presult, &sresult, sizeof(parsertree));
112 (*presult)->finished = 1;
113
114 root = (*presult)->root;
115 }
116
117 xl = malloc(sizeof(expressionlist) + sizeof(searchASTExpr) * count);
118 xl->next = (*presult)->exprlist;
119 (*presult)->exprlist = xl;
120
121 ap = xl->expr;
122 for(i=count-1,pp=stack[stackpos];i>=0;i--,pp=npp) {
123 npp = pp->next;
124 memcpy(&ap[i], &pp->expr, sizeof(searchASTExpr));
125 free(pp);
126 }
127 *root = NSASTManualNode(pfn, count, ap);
128
129 freesstring(str);
130 }
131
132function: IDENTIFIER
133 {
134 if(stackpos >= MAXSTACKSIZE - 1) {
135 yyerror("function stack overflow");
136 YYERROR;
137 }
138
139 stackcount[stackpos] = 0;
140 stack[stackpos] = NULL;
141
142 stackpos++;
143 };
144
145argumentlist: /* empty */ | WHITESPACE argument argumentlist;
146
147argument:
148 invocation | literal
149 {
150 sstring *str = $1;
151 parserlist *l = malloc(sizeof(parserlist));
152
153 if(str) {
154 stringlist *sl;
155 l->expr = NSASTLiteral(str->content);
156
157 sl = malloc(sizeof(stringlist));
158 sl->data = str;
159 sl->next = (*presult)->strlist;
160 (*presult)->strlist = sl;
161 } else {
162 l->expr = NSASTLiteral("");
163 }
164
165 l->next = stack[stackpos - 1];
166 stack[stackpos - 1] = l;
167 stackcount[stackpos - 1]++;
168
169 }
170 ;
171
172literal: IDENTIFIER | STRING;