6 #include "grammarcom.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.
29 fmtprint(cfmt
, "#line %lP\n", pos
);
33 typecheckgram(Typecheck
*tc
, GTop
*gtop
)
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
);
52 error(gtop
->pos
, "%s is already declared", gtop
->name
);
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
;
61 fmtprint(&fmt
, "\t\ttg = typegram1(%N, mkGram(%N));\n", gtop
->name
, gtop
->name
);
62 }else if(gtop
->xflag
== N("extend")){
64 v
= lookupvar(tc
->scope
, gtop
->name
);
66 error(gtop
->pos
, "%s is not declared", gtop
->name
);
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());
77 }else if(gtop
->extendl
){
79 for(nl
=gtop
->extendl
; nl
; nl
=nl
->tl
){
80 v
= lookupvar(tc
->scope
, nl
->hd
);
82 error(gtop
->pos
, "%s is not declared", nl
->hd
);
85 if(v
->realtype
== nil
|| v
->realtype
->op
!= TypeGram
){
86 error(gtop
->pos
, "%s is not a grammar", nl
->hd
);
92 if(typemax(tg
, v
->realtype
, &tg
) < 0){
93 error(gtop
->pos
, "cannot extend %T and %T", tg
, v
->realtype
);
97 v
= lookupvar(tc
->scope
, gtop
->name
);
99 error(gtop
->pos
, "%s is already declared", gtop
->name
);
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());
109 fmtprint(&fmt
, "\t\ttg = %#lT;\n", tg
);
111 panic("typecheckgram");
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.
118 fmtprint(&fmt
, "\t\t__types__[%d] = tg;\n", tg
->id
);
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
);
131 typecheckgstmt(Typecheck
*tc
, Type
*tg
, GStmt
*stmt
)
142 left
= gramsym(tg
, stmt
->name
);
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");
151 for(tl
=stmt
->terml
; tl
; tl
=tl
->tl
){
155 error(term
->pos
, "can only ignore strings and regexps");
158 gramignore(tg
->gram
, term
->text
, RegexpLiteral
, 0);
160 fmtprint(cfmt
, "\t\tgramignore(g, %N, %d, 0);\n",
161 term
->text
, RegexpLiteral
);
164 if(gramignore(tg
->gram
, term
->text
, RegexpEgrep
|term
->flags
, 1) == nil
){
165 error(term
->pos
, "invalid regexp in ignore");
168 fmtprint(cfmt
, "\t\tgramignore(g, %N, %d, 0);\n",
169 term
->text
, RegexpEgrep
|term
->flags
);
176 for(tl
=stmt
->terml
; tl
; tl
=tl
->tl
){
180 gramsym(tg
, term
->text
)->nocopy
= 1;
182 fmtprint(cfmt
, "\t\tgramsym(tg, %N)->nocopy = 1;\n", term
->text
);
186 error(term
->pos
, "can only nocopy names");
194 for(nl
=stmt
->namel
; nl
; nl
=nl
->tl
){
195 gramprec(tg
->gram
, nl
->hd
, stmt
->assoc
, CfgPrecPriority
, 1);
197 fmtprint(cfmt
, "\t\tgramprec(g, %N, %d, %d, 1);\n", nl
->hd
, stmt
->assoc
, CfgPrecPriority
);
202 if(lenNameL(stmt
->namel
) < 2){
203 error(stmt
->pos
, "meaningless precedence");
206 pkind
= CfgPrecPriority
;
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");
213 fmtprint(cfmt
, "\t\tif(grampriority(g, %N, %N, %d) < 0) panic(\"grampriority: %%r\");\n",
214 nl
->hd
, nl
->tl
->hd
, stmt
->prefer
);
221 typecheckgrule(Typecheck
*tc
, Type
*tg
, CfgSym
*left
, GRule
*rule
)
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
)
234 sl
= mkCfgSymL(s
, sl
);
236 fmtprint(cfmt
, "\t\t\t\tsl = mkCfgSymL(s, sl);\n");
241 fmtprint(cfmt
, "\t\t\t\tsl = revCfgSymL(sl);\n");
242 fmtprint(cfmt
, "\t\t\t\tGramPrec *p = 0;\n");
244 p
= gramprec(tg
->gram
, rule
->prec
, 0, 0, 0);
246 error(rule
->pos
, "unknown precedence %s", rule
->prec
);
250 fmtprint(cfmt
, "\t\t\t\tp = gramprec(g, %N, 0, 0, 0);\n", rule
->prec
);
252 fmtprint(cfmt
, "\t\t\t\tif(p == 0) panic(\"gramprec %s\", %N);\n", rule
->prec
);
254 gramaddrule(tg
, p
, left
, sl
);
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");
262 typecheckgterm(Type
*tg
, GTerm
*term
)
269 if((s
= gramregexp(tg
, term
->text
, term
->flags
, 1)) == nil
){
270 error(term
->pos
, "invalid regexp");
273 fmtprint(cfmt
, "\t\t\t\ts = gramregexp(tg, %N, %d, 0);\n", term
->text
, term
->flags
);
277 s
= gramsym(tg
, term
->text
);
278 fmtprint(cfmt
, "\t\t\t\ts = gramsym(tg, %N);\n", term
->text
);
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
);
287 panic("typecheckgterm");
292 typecheckgexpr(Typecheck
*tc
, Expr
*expr
, int kind
)
298 panic("typecheckgexpr %#P", expr
->pos
);
301 noassign(expr
, kind
);
302 nosideeffect(expr
, kind
);
303 if(typecheckexpr(tc
, expr
->e1
, Value
) < 0)
305 t
= typechecktype(tc
, expr
->typex
);
315 typegramdot(Type
*t
, Name name
)
319 s
= gramlooksym(t
->gram
, name
);
322 return typegramsym(t
, name
, s
);
326 cgengraminit(Cbuf
*cb
)
330 for(nl
=revNameL(graminit
); nl
; nl
=nl
->tl
)
331 fmtprint(&cb
->topfmt
, "%s", nl
->hd
);
335 mkGTop(Name xflag
, Name name
, NameL
*extendl
, GStmtL
*stmtl
)
339 t
= emalloc(sizeof *t
);
343 t
->extendl
= extendl
;
353 r
= emalloc(sizeof *r
);
363 s
= emalloc(sizeof *s
);
374 t
= emalloc(sizeof *t
);