switch -O2 to -O1 for zetacom compilation
[xoc.git] / zeta / grammarcom.c
blob9864fe06b61af5f0f6b3426346576f7b1927a93a
1 #include "a.h"
2 #include "type.h"
3 #include "runtime.h"
4 #include "grammar.h"
5 #include "compile.h"
6 #include "grammarcom.h"
7 #include "listimpl.h"
9 static NameL *graminit;
11 void typecheckgstmt(Typecheck*, Type*, GStmt*);
12 void typecheckgrule(Typecheck *tc, Type*, CfgSym *left, GRule *rule);
13 CfgSym* typecheckgterm(Type*, GTerm *term);
15 // Grammars are a bit different from the usual compiler stuff,
16 // because there is a lot of state that has to get recreated
17 // when the module gets loaded, and it's not easy to just
18 // traverse the state itself (the grammar and its rules) to
19 // generate C code that will reconstruct the state. Instead,
20 // we just write down everything we've done as we do it.
21 // Remember, a compiler is just an interpreter with the actions
22 // turned into print statements.
23 static Fmt *cfmt;
25 static void
26 line(Pos pos)
28 if(linenumbers)
29 fmtprint(cfmt, "#line %lP\n", pos);
32 void
33 typecheckgram(Typecheck *tc, GTop *gtop)
35 Var *v;
36 GStmtL *l;
37 Gram *g;
38 Type *tg;
39 Fmt fmt;
40 char *s;
41 NameL *nl;
42 Name x;
44 fmtstrinit(&fmt);
45 cfmt = &fmt;
46 v = nil;
47 line(gtop->pos);
48 fmtprint(&fmt, "\t{\n\t\tType *tg;\n", tg);
49 if(gtop->xflag != N("extend") && gtop->extendl == nil){
50 v = lookupvar(tc->scope, gtop->name);
51 if(v){
52 error(gtop->pos, "%s is already declared", gtop->name);
53 return;
55 g = mkGram(gtop->name/*, gtop->xflag == N("extensible")*/);
56 g->type = typegram1(gtop->name, g);
57 v = declarevar(gtop->pos, tc->scope, gtop->name, typetype());
58 v->realtype = g->type;
59 v->cname = nil;
60 tg = g->type;
61 fmtprint(&fmt, "\t\ttg = typegram1(%N, mkGram(%N));\n", gtop->name, gtop->name);
62 }else if(gtop->xflag == N("extend")){
63 static int anon;
64 v = lookupvar(tc->scope, gtop->name);
65 if(v == nil){
66 error(gtop->pos, "%s is not declared", gtop->name);
67 return;
69 // TODO: better name generation (include module name)
70 x = nameprint("%s_xG_%d", topscope->frame->prefix, anon++);
71 tg = typegramxl(v->realtype, x, nil);
72 fmtprint(&fmt, "\t\ttg = typegramxl(%#lT, %N, nil);\n", v->realtype, x);
73 g = v->realtype->gram;
74 v = declarevar(gtop->pos, tc->scope, x, typetype());
75 v->realtype = tg;
76 v->cname = nil;
77 }else if(gtop->extendl){
78 tg = nil;
79 for(nl=gtop->extendl; nl; nl=nl->tl){
80 v = lookupvar(tc->scope, nl->hd);
81 if(v == nil){
82 error(gtop->pos, "%s is not declared", nl->hd);
83 return;
85 if(v->realtype == nil || v->realtype->op != TypeGram){
86 error(gtop->pos, "%s is not a grammar", nl->hd);
87 return;
89 if(tg == nil)
90 tg = v->realtype;
91 else
92 if(typemax(tg, v->realtype, &tg) < 0){
93 error(gtop->pos, "cannot extend %T and %T", tg, v->realtype);
94 return;
97 v = lookupvar(tc->scope, gtop->name);
98 if(v){
99 error(gtop->pos, "%s is already declared", gtop->name);
100 return;
102 tg = typegramsym(tg, nil, nil);
103 tg = typegramx(tg, nil);
104 fmtprint(&fmt, "\t\t%#T = %#lT;\n", tg, tg);
105 tg = typegramx(tg, mkNameL(gtop->name, tg->gramx));
106 v = declarevar(gtop->pos, tc->scope, gtop->name, typetype());
107 v->cname = nil;
108 v->realtype = tg;
109 fmtprint(&fmt, "\t\ttg = %#lT;\n", tg);
110 }else{
111 panic("typecheckgram");
112 return;
115 // The __types__ array isn't yet set up, but we'd like to be able
116 // to use %#T to refer to tg, so set up tg's entry.
117 line(gtop->pos);
118 fmtprint(&fmt, "\t\t__types__[%d] = tg;\n", tg->id);
120 line(gtop->pos);
121 fmtprint(&fmt, "\t\tGram *g = tg->gram;\n");
122 for(l=gtop->stmtl; l; l=l->tl)
123 typecheckgstmt(tc, tg, l->hd);
124 fmtprint(&fmt, "\t}\n");
125 s = fmtstrflush(&fmt);
126 graminit = mkNameL(nameof(s), graminit);
127 free(s);
130 void
131 typecheckgstmt(Typecheck *tc, Type *tg, GStmt *stmt)
133 GRuleL *rl;
134 CfgSym *left;
135 NameL *nl;
136 CfgPrecKind pkind;
137 GTerm *term;
138 GTermL *tl;
140 switch(stmt->op){
141 case GStmtRules:
142 left = gramsym(tg, stmt->name);
143 line(stmt->pos);
144 fmtprint(cfmt, "\t\t{\n\t\t\tCfgSym *left = gramsym(tg, %N);\n", stmt->name);
145 for(rl=stmt->rulel; rl; rl=rl->tl)
146 typecheckgrule(tc, tg, left, rl->hd);
147 fmtprint(cfmt, "\t\t}\n");
148 break;
150 case GStmtIgnore:
151 for(tl=stmt->terml; tl; tl=tl->tl){
152 term = tl->hd;
153 switch(term->op){
154 case GTermName:
155 error(term->pos, "can only ignore strings and regexps");
156 break;
157 case GTermString:
158 gramignore(tg->gram, term->text, RegexpLiteral, 0);
159 line(term->pos);
160 fmtprint(cfmt, "\t\tgramignore(g, %N, %d, 0);\n",
161 term->text, RegexpLiteral);
162 break;
163 case GTermRegexp:
164 if(gramignore(tg->gram, term->text, RegexpEgrep|term->flags, 1) == nil){
165 error(term->pos, "invalid regexp in ignore");
166 break;
168 fmtprint(cfmt, "\t\tgramignore(g, %N, %d, 0);\n",
169 term->text, RegexpEgrep|term->flags);
170 break;
173 break;
175 case GStmtNoCopy:
176 for(tl=stmt->terml; tl; tl=tl->tl){
177 term = tl->hd;
178 switch(term->op){
179 case GTermName:
180 gramsym(tg, term->text)->nocopy = 1;
181 line(stmt->pos);
182 fmtprint(cfmt, "\t\tgramsym(tg, %N)->nocopy = 1;\n", term->text);
183 break;
184 case GTermRegexp:
185 case GTermString:
186 error(term->pos, "can only nocopy names");
187 break;
190 break;
192 case GStmtAssoc:
193 line(stmt->pos);
194 for(nl=stmt->namel; nl; nl=nl->tl){
195 gramprec(tg->gram, nl->hd, stmt->assoc, CfgPrecPriority, 1);
196 line(stmt->pos);
197 fmtprint(cfmt, "\t\tgramprec(g, %N, %d, %d, 1);\n", nl->hd, stmt->assoc, CfgPrecPriority);
199 break;
201 case GStmtPriority:
202 if(lenNameL(stmt->namel) < 2){
203 error(stmt->pos, "meaningless precedence");
204 break;
206 pkind = CfgPrecPriority;
207 if(stmt->prefer)
208 pkind = CfgPrecPrefer;
209 for(nl=stmt->namel; nl->tl; nl=nl->tl){
210 if(grampriority(tg->gram, nl->hd, nl->tl->hd, stmt->prefer) < 0)
211 error(stmt->pos, "grampriority: %r");
212 line(stmt->pos);
213 fmtprint(cfmt, "\t\tif(grampriority(g, %N, %N, %d) < 0) panic(\"grampriority: %%r\");\n",
214 nl->hd, nl->tl->hd, stmt->prefer);
216 break;
220 void
221 typecheckgrule(Typecheck *tc, Type *tg, CfgSym *left, GRule *rule)
223 GTermL *tl;
224 CfgSymL *sl;
225 GramPrec *p;
226 CfgSym *s;
228 sl = nil;
229 line(rule->pos);
230 fmtprint(cfmt, "\t\t\t{\n\t\t\t\tCfgSymL *sl = 0; CfgSym *s;\n");
231 for(tl=rule->terml; tl; tl=tl->tl){
232 if((s = typecheckgterm(tg, tl->hd)) == nil)
233 return;
234 sl = mkCfgSymL(s, sl);
235 line(tl->hd->pos);
236 fmtprint(cfmt, "\t\t\t\tsl = mkCfgSymL(s, sl);\n");
238 sl = revCfgSymL(sl);
239 p = nil;
240 line(rule->pos);
241 fmtprint(cfmt, "\t\t\t\tsl = revCfgSymL(sl);\n");
242 fmtprint(cfmt, "\t\t\t\tGramPrec *p = 0;\n");
243 if(rule->prec){
244 p = gramprec(tg->gram, rule->prec, 0, 0, 0);
245 if(p == nil){
246 error(rule->pos, "unknown precedence %s", rule->prec);
247 return;
249 line(rule->pos);
250 fmtprint(cfmt, "\t\t\t\tp = gramprec(g, %N, 0, 0, 0);\n", rule->prec);
251 line(rule->pos);
252 fmtprint(cfmt, "\t\t\t\tif(p == 0) panic(\"gramprec %s\", %N);\n", rule->prec);
254 gramaddrule(tg, p, left, sl);
255 line(rule->pos);
256 fmtprint(cfmt, "\t\t\t\tgramaddrule(tg, p, left, sl);\n");
257 fmtprint(cfmt, "\t\t\t\tfreeCfgSymL(sl);\n");
258 fmtprint(cfmt, "\t\t\t}\n");
261 CfgSym*
262 typecheckgterm(Type *tg, GTerm *term)
264 CfgSym *s;
266 line(term->pos);
267 switch(term->op){
268 case GTermRegexp:
269 if((s = gramregexp(tg, term->text, term->flags, 1)) == nil){
270 error(term->pos, "invalid regexp");
271 return nil;
273 fmtprint(cfmt, "\t\t\t\ts = gramregexp(tg, %N, %d, 0);\n", term->text, term->flags);
274 return s;
276 case GTermName:
277 s = gramsym(tg, term->text);
278 fmtprint(cfmt, "\t\t\t\ts = gramsym(tg, %N);\n", term->text);
279 return s;
281 case GTermString:
282 term->str = nameof(cunescapestring(nametostr(term->text), -1));
283 s = gramliteral(tg, term->str);
284 fmtprint(cfmt, "\t\t\t\ts = gramliteral(tg, %N);\n", term->str);
285 return s;
287 panic("typecheckgterm");
288 return nil;
292 typecheckgexpr(Typecheck *tc, Expr *expr, int kind)
294 Type *t;
296 switch(expr->op){
297 default:
298 panic("typecheckgexpr %#P", expr->pos);
300 case ExprParse:
301 noassign(expr, kind);
302 nosideeffect(expr, kind);
303 if(typecheckexpr(tc, expr->e1, Value) < 0)
304 return -1;
305 t = typechecktype(tc, expr->typex);
306 if(t == nil)
307 return -1;
308 expr->type = t;
309 break;
311 return 0;
314 Type*
315 typegramdot(Type *t, Name name)
317 CfgSym *s;
319 s = gramlooksym(t->gram, name);
320 if(s == nil)
321 return nil;
322 return typegramsym(t, name, s);
325 void
326 cgengraminit(Cbuf *cb)
328 NameL *nl;
330 for(nl=revNameL(graminit); nl; nl=nl->tl)
331 fmtprint(&cb->topfmt, "%s", nl->hd);
334 GTop*
335 mkGTop(Name xflag, Name name, NameL *extendl, GStmtL *stmtl)
337 GTop *t;
339 t = emalloc(sizeof *t);
340 t->pos = yylastpos;
341 t->xflag = xflag;
342 t->name = name;
343 t->extendl = extendl;
344 t->stmtl = stmtl;
345 return t;
348 GRule*
349 mkGRule(void)
351 GRule *r;
353 r = emalloc(sizeof *r);
354 r->pos = yylastpos;
355 return r;
358 GStmt*
359 mkGStmt(GStmtOp op)
361 GStmt *s;
363 s = emalloc(sizeof *s);
364 s->op = op;
365 s->pos = yylastpos;
366 return s;
369 GTerm*
370 mkGTerm(GTermOp op)
372 GTerm *t;
374 t = emalloc(sizeof *t);
375 t->op = op;
376 t->pos = yylastpos;
377 return t;
380 LISTIMPL(GStmt)
381 LISTIMPL(GRule)
382 LISTIMPL(GTerm)