1 
2 %token_prefix XLAT_
3 %token_type {FParseToken}
4 %token_destructor {}	// just to avoid a compiler warning
5 %name XlatParse
6 %extra_argument { FParseContext *context }
7 %syntax_error { context->PrintError("syntax error");}
8 
9 
10 main ::= translation_unit.
11 
12 translation_unit ::= . /* empty */
13 translation_unit ::= translation_unit external_declaration.
14 
15 external_declaration ::= define_statement.
16 external_declaration ::= enum_statement.
17 external_declaration ::= linetype_declaration.
18 external_declaration ::= boom_declaration.
19 external_declaration ::= sector_declaration.
20 external_declaration ::= lineflag_declaration.
21 external_declaration ::= sector_bitmask.
22 external_declaration ::= maxlinespecial_def.
23 external_declaration ::= NOP.
24 
25 
26 %left OR.
27 %left XOR.
28 %left AND.
29 %left MINUS PLUS.
30 %left MULTIPLY DIVIDE MODULUS.
31 %left NEG.
32 
33 %type exp {int}
exp(A)34 exp(A) ::= NUM(B).					{ A = B.val; }
exp(A)35 exp(A) ::= exp(B) PLUS exp(C).		{ A = B + C; }
exp(A)36 exp(A) ::= exp(B) MINUS exp(C).		{ A = B - C; }
exp(A)37 exp(A) ::= exp(B) MULTIPLY exp(C).	{ A = B * C; }
exp(A)38 exp(A) ::= exp(B) DIVIDE exp(C).	{ if (C != 0) A = B / C; else context->PrintError("Division by zero"); }
exp(A)39 exp(A) ::= exp(B) MODULUS exp(C).	{ if (C != 0) A = B % C; else context->PrintError("Division by zero"); }
exp(A)40 exp(A) ::= exp(B) OR exp(C).		{ A = B | C; }
exp(A)41 exp(A) ::= exp(B) AND exp(C).		{ A = B & C; }
exp(A)42 exp(A) ::= exp(B) XOR exp(C).		{ A = B ^ C; }
exp(A)43 exp(A) ::= MINUS exp(B). [NEG]		{ A = -B; }
exp(A)44 exp(A) ::= LPAREN exp(B) RPAREN.	{ A = B; }
45 
46 
47 //==========================================================================
48 //
49 // define
50 //
51 //==========================================================================
52 
SYM(A)53 define_statement ::= DEFINE SYM(A) LPAREN exp(B) RPAREN.
54 {
55 	context->AddSym (A.sym, B);
56 }
57 
58 //==========================================================================
59 //
60 // enum
61 //
62 //==========================================================================
63 
64 enum_statement ::= enum_open enum_list RBRACE.
65 
66 enum_open ::= ENUM LBRACE.
67 {
68 	context->EnumVal = 0;
69 }
70 
71 enum_list ::= . /* empty */
72 enum_list ::= single_enum.
73 enum_list ::= enum_list COMMA single_enum.
74 
SYM(A)75 single_enum ::= SYM(A).
76 {
77 	context->AddSym (A.sym, context->EnumVal++);
78 }
79 
SYM(A)80 single_enum ::= SYM(A) EQUALS exp(B).
81 {
82 	context->AddSym (A.sym, B);
83 	context->EnumVal = B+1;
84 }
85 
86 //==========================================================================
87 //
88 // standard linetype
89 //
90 //==========================================================================
91 
92 %type linetype_exp {int}
linetype_exp(Z)93 linetype_exp(Z) ::= exp(A).
94 {
95 	Z = static_cast<XlatParseContext *>(context)->DefiningLineType = A;
96 }
97 
linetype_exp(linetype)98 linetype_declaration ::= linetype_exp(linetype) EQUALS exp(flags) COMMA exp(special) LPAREN special_args(arg) RPAREN.
99 {
100 	SimpleLineTranslations.SetVal(linetype,
101 		FLineTrans(special&0xffff, flags+arg.addflags, arg.args[0], arg.args[1], arg.args[2], arg.args[3], arg.args[4]));
102 	static_cast<XlatParseContext *>(context)->DefiningLineType = -1;
103 }
104 
SYM(S)105 linetype_declaration ::= linetype_exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN.
106 {
107 	Printf ("%s, line %d: %s is undefined\n", context->SourceFile, context->SourceLine, S.sym);
108 	static_cast<XlatParseContext *>(context)->DefiningLineType = -1;
109 }
110 
111 %type exp_with_tag {int}
exp_with_tag(A)112 exp_with_tag(A) ::= NUM(B).		{ XlatExpressions.Push(B.val); A = XlatExpressions.Push(XEXP_Const); }
exp_with_tag(A)113 exp_with_tag(A) ::= TAG.									{ A = XlatExpressions.Push(XEXP_Tag); }
exp_with_tag(A)114 exp_with_tag(A) ::= exp_with_tag PLUS exp_with_tag.			{ A = XlatExpressions.Push(XEXP_Add); }
exp_with_tag(A)115 exp_with_tag(A) ::= exp_with_tag MINUS exp_with_tag.		{ A = XlatExpressions.Push(XEXP_Sub); }
exp_with_tag(A)116 exp_with_tag(A) ::= exp_with_tag MULTIPLY exp_with_tag.		{ A = XlatExpressions.Push(XEXP_Mul); }
exp_with_tag(A)117 exp_with_tag(A) ::= exp_with_tag DIVIDE exp_with_tag.		{ A = XlatExpressions.Push(XEXP_Div); }
exp_with_tag(A)118 exp_with_tag(A) ::= exp_with_tag MODULUS exp_with_tag.		{ A = XlatExpressions.Push(XEXP_Mod); }
exp_with_tag(A)119 exp_with_tag(A) ::= exp_with_tag OR exp_with_tag.			{ A = XlatExpressions.Push(XEXP_Or);  }
exp_with_tag(A)120 exp_with_tag(A) ::= exp_with_tag AND exp_with_tag.			{ A = XlatExpressions.Push(XEXP_And); }
exp_with_tag(A)121 exp_with_tag(A) ::= exp_with_tag XOR exp_with_tag.			{ A = XlatExpressions.Push(XEXP_Xor); }
exp_with_tag(A)122 exp_with_tag(A) ::= MINUS exp_with_tag. [NEG]				{ A = XlatExpressions.Push(XEXP_Neg); }
exp_with_tag(A)123 exp_with_tag(A) ::= LPAREN exp_with_tag(B) RPAREN.			{ A = B; }
124 
125 
126 %type special_arg {SpecialArg}
127 
special_arg(Z)128 special_arg(Z) ::= exp_with_tag(A).
129 {
130 	if (XlatExpressions[A] == XEXP_Tag)
131 	{ // Store tags directly
132 		Z.arg = 0;
133 		Z.argop = ARGOP_Tag;
134 		XlatExpressions.Delete(A);
135 	}
136 	else
137 	{ // Try and evaluate it. If it's a constant, store it and erase the
138 	  // expression. Otherwise, store the index to the expression. We make
139 	  // no attempt to simplify non-constant expressions.
140 		FXlatExprState state;
141 		int val;
142 		const int *endpt;
143 		int *xnode;
144 
145 		state.linetype = static_cast<XlatParseContext *>(context)->DefiningLineType;
146 		state.tag = 0;
147 		state.bIsConstant = true;
148 		xnode = &XlatExpressions[A];
149 		endpt = XlatExprEval[*xnode](&val, xnode, &state);
150 		if (state.bIsConstant)
151 		{
152 			Z.arg = val;
153 			Z.argop = ARGOP_Const;
154 			endpt++;
155 			assert(endpt >= &XlatExpressions[0]);
156 			XlatExpressions.Resize((unsigned)(endpt - &XlatExpressions[0]));
157 		}
158 		else
159 		{
160 			Z.arg = A;
161 			Z.argop = ARGOP_Expr;
162 		}
163 	}
164 }
165 
166 %type multi_special_arg {SpecialArgs}
167 
multi_special_arg(Z)168 multi_special_arg(Z) ::= special_arg(A).
169 {
170 	Z.addflags = A.argop << LINETRANS_TAGSHIFT;
171 	Z.argcount = 1;
172 	Z.args[0] = A.arg;
173 	Z.args[1] = 0;
174 	Z.args[2] = 0;
175 	Z.args[3] = 0;
176 	Z.args[4] = 0;
177 }
multi_special_arg(Z)178 multi_special_arg(Z) ::= multi_special_arg(A) COMMA special_arg(B).
179 {
180 	Z = A;
181 	if (Z.argcount < LINETRANS_MAXARGS)
182 	{
183 		Z.addflags |= B.argop << (LINETRANS_TAGSHIFT + Z.argcount * TAGOP_NUMBITS);
184 		Z.args[Z.argcount] = B.arg;
185 		Z.argcount++;
186 	}
187 	else if (Z.argcount++ == LINETRANS_MAXARGS)
188 	{
189 		context->PrintError("Line special has too many arguments\n");
190 	}
191 }
192 
193 %type special_args {SpecialArgs}
194 
special_args(Z)195 special_args(Z) ::= . /* empty */
196 {
197 	Z.addflags = 0;
198 	Z.argcount = 0;
199 	Z.args[0] = 0;
200 	Z.args[1] = 0;
201 	Z.args[2] = 0;
202 	Z.args[3] = 0;
203 	Z.args[4] = 0;
204 }
special_args(Z)205 special_args(Z) ::= multi_special_arg(A).
206 {
207 	Z = A;
208 }
209 
210 //==========================================================================
211 //
212 // boom generalized linetypes
213 //
214 //==========================================================================
215 
216 %type list_val {ListFilter}
217 %type arg_list {MoreFilters *}
218 %type boom_args {ParseBoomArg}
219 %type boom_op {int}
220 %type boom_selector {int}
221 %type boom_line {FBoomArg}
222 %type boom_body {MoreLines *}
223 
224 
exp(special)225 boom_declaration ::= LBRACKET exp(special) RBRACKET LPAREN exp(firsttype) COMMA exp(lasttype) RPAREN LBRACE boom_body(stores) RBRACE.
226 {
227 	int i;
228 	MoreLines *probe;
229 
230 	if (NumBoomish == MAX_BOOMISH)
231 	{
232 		MoreLines *probe = stores;
233 
234 		while (probe != NULL)
235 		{
236 			MoreLines *next = probe->next;
237 			delete probe;
238 			probe = next;
239 		}
240 		Printf ("%s, line %d: Too many BOOM translators\n", context->SourceFile, context->SourceLine);
241 	}
242 	else
243 	{
244 		Boomish[NumBoomish].FirstLinetype = firsttype;
245 		Boomish[NumBoomish].LastLinetype = lasttype;
246 		Boomish[NumBoomish].NewSpecial = special;
247 
248 		for (i = 0, probe = stores; probe != NULL; i++)
249 		{
250 			MoreLines *next = probe->next;
251 			Boomish[NumBoomish].Args.Push(probe->arg);
252 			delete probe;
253 			probe = next;
254 		}
255 		NumBoomish++;
256 	}
257 }
258 
boom_body(A)259 boom_body(A) ::= . /* empty */
260 {
261 	A = NULL;
262 }
boom_body(A)263 boom_body(A) ::= boom_line(B) boom_body(C).
264 {
265 	A = new MoreLines;
266 	A->next = C;
267 	A->arg = B;
268 }
269 
boom_line(A)270 boom_line(A) ::= boom_selector(sel) boom_op(op) boom_args(args).
271 {
272 	A.bOrExisting = (op == OR_EQUAL);
273 	A.bUseConstant = (args.filters == NULL);
274 	A.ArgNum = sel;
275 	A.ConstantValue = args.constant;
276 	A.AndValue = args.mask;
277 
278 	if (args.filters != NULL)
279 	{
280 		int i;
281 		MoreFilters *probe;
282 
283 		for (i = 0, probe = args.filters; probe != NULL; i++)
284 		{
285 			MoreFilters *next = probe->next;
286 			if (i < 15)
287 			{
288 				A.ResultFilter[i] = probe->filter.filter;
289 				A.ResultValue[i] = probe->filter.value;
290 			}
291 			else if (i == 15)
292 			{
293 				context->PrintError ("Lists can only have 15 elements");
294 			}
295 			delete probe;
296 			probe = next;
297 		}
298 		A.ListSize = i > 15 ? 15 : i;
299 	}
300 }
301 
boom_selector(A)302 boom_selector(A) ::= FLAGS.		{ A = 4; }
boom_selector(A)303 boom_selector(A) ::= ARG2.		{ A = 0; }
boom_selector(A)304 boom_selector(A) ::= ARG3.		{ A = 1; }
boom_selector(A)305 boom_selector(A) ::= ARG4.		{ A = 2; }
boom_selector(A)306 boom_selector(A) ::= ARG5.		{ A = 3; }
307 
boom_op(A)308 boom_op(A) ::= EQUALS.			{ A = '='; }
boom_op(A)309 boom_op(A) ::= OR_EQUAL.		{ A = OR_EQUAL; }
310 
boom_args(A)311 boom_args(A) ::= exp(B).
312 {
313 	A.constant = B;
314 	A.filters = NULL;
315 }
boom_args(A)316 boom_args(A) ::= exp(B) LBRACKET arg_list(C) RBRACKET.
317 {
318 	A.mask = B;
319 	A.filters = C;
320 }
321 
arg_list(A)322 arg_list(A) ::= list_val(B).
323 {
324 	A = new MoreFilters;
325 	A->next = NULL;
326 	A->filter = B;
327 }
arg_list(A)328 arg_list(A) ::= list_val(B) COMMA arg_list(C).
329 {
330 	A = new MoreFilters;
331 	A->next = C;
332 	A->filter = B;
333 }
334 
list_val(A)335 list_val(A) ::= exp(B) COLON exp(C).
336 {
337 	A.filter = B;
338 	A.value = C;
339 }
340 
341 //==========================================================================
342 //
343 // max line special
344 //
345 //==========================================================================
346 
exp(mx)347 maxlinespecial_def ::= MAXLINESPECIAL EQUALS exp(mx) SEMICOLON.
348 {
349 	// Just kill all specials higher than the max.
350 	// If the translator wants to redefine some later, just let it.
351 	SimpleLineTranslations.Resize(mx+1);
352 }
353 
354 //==========================================================================
355 //
356 // sector types
357 //
358 //==========================================================================
359 
360 %type sector_op {int}
361 
exp(from)362 sector_declaration ::= SECTOR exp(from) EQUALS exp(to) SEMICOLON.
363 {
364 	FSectorTrans tr(to, true);
365 	SectorTranslations.SetVal(from, tr);
366 }
367 
SYM(sy)368 sector_declaration ::= SECTOR exp EQUALS SYM(sy) SEMICOLON.
369 {
370 	Printf("Unknown constant '%s'\n", sy.sym);
371 }
372 
exp(from)373 sector_declaration ::= SECTOR exp(from) EQUALS exp(to) NOBITMASK SEMICOLON.
374 {
375 	FSectorTrans tr(to, false);
376 	SectorTranslations.SetVal(from, tr);
377 }
378 
exp(mask)379 sector_bitmask ::= SECTOR BITMASK exp(mask) sector_op(op) exp(shift) SEMICOLON.
380 {
381 	FSectorMask sm = { mask, op, shift};
382 	SectorMasks.Push(sm);
383 }
384 
exp(mask)385 sector_bitmask ::= SECTOR BITMASK exp(mask) SEMICOLON.
386 {
387 	FSectorMask sm = { mask, 0, 0};
388 	SectorMasks.Push(sm);
389 }
390 
exp(mask)391 sector_bitmask ::= SECTOR BITMASK exp(mask) CLEAR SEMICOLON.
392 {
393 	FSectorMask sm = { mask, 0, 1};
394 	SectorMasks.Push(sm);
395 }
396 
sector_op(A)397 sector_op(A) ::= LSHASSIGN.		{ A = 1; }
sector_op(A)398 sector_op(A) ::= RSHASSIGN.		{ A = -1; }
399 
400 %type lineflag_op {int}
401 
exp(from)402 lineflag_declaration ::= LINEFLAG exp(from) EQUALS exp(to) SEMICOLON.
403 {
404 	if (from >= 0 && from < 16)
405 	{
406 		LineFlagTranslations[from].newvalue = to;
407 		LineFlagTranslations[from].ismask = false;
408 	}
409 }
410 
exp(from)411 lineflag_declaration ::= LINEFLAG exp(from) AND exp(mask) SEMICOLON.
412 {
413 	if (from >= 0 && from < 16)
414 	{
415 		LineFlagTranslations[from].newvalue = mask;
416 		LineFlagTranslations[from].ismask = true;
417 	}
418 }