this repo has no description
1%require "3.0.2"
2%defines
3%define parser_class_name {RezParser}
4%skeleton "lalr1.cc"
5
6%locations;
7
8%define api.token.constructor
9%define api.value.type variant
10%define parse.assert
11
12%token<std::string> IDENTIFIER;
13%token<int> CHARLIT;
14%token<std::string> STRINGLIT;
15%token<int> INTLIT;
16
17%token<std::string> BADTOKEN;
18
19
20%token LEFTBRACE "{";
21%token RIGHTBRACE "}";
22%token LEFTBRACKET "[";
23%token RIGHTBRACKET "]";
24%token LEFTPAREN "(";
25%token RIGHTPAREN ")";
26%token SEMICOLON ";";
27%token COMMA ",";
28%token PLUS "+";
29%token MINUS "-";
30%token DIVIDE "/";
31%token STAR "*";
32%token ASSIGN "=";
33%token COLON ":";
34%token SHIFTLEFT "<<";
35%token SHIFTRIGHT ">>";
36%token EQUAL "==";
37%token NOTEQUAL "!=";
38%token AND "&";
39%token OR "|";
40%token XOR "^";
41%token COMPL "~";
42%token DOLLAR "$";
43
44%token TYPE "type";
45%token RESOURCE "resource";
46%token DATA "data";
47%token READ "read";
48%token INCLUDE "include";
49%token CHANGE "change";
50%token DELETE "delete";
51
52
53%token ARRAY "array";
54%token SWITCH "switch";
55%token CASE "case";
56%token AS "as";
57%token FILL "fill";
58%token ALIGN "align";
59%token HEX "hex";
60%token KEY "key";
61%token WIDE "wide";
62%token LITERAL "literal";
63%token UNSIGNED "unsigned";
64%token BINARY "binary";
65
66%token BOOLEAN "boolean";
67%token BIT "bit";
68%token NIBBLE "nibble";
69%token BYTE "byte";
70%token CHAR "char";
71%token WORD "word";
72%token INTEGER "integer";
73%token LONG "long";
74%token LONGINT "longint";
75%token PSTRING "pstring";
76%token WSTRING "wstring";
77%token STRING "string";
78%token POINT "point";
79%token RECT "rect";
80%token BITSTRING "bitstring";
81
82%token FUN_COUNTOF "$$countof";
83%token FUN_ARRAYINDEX "$$arrayindex";
84%token FUN_READ "$$read";
85%token FUN_BITFIELD "$$bitfield";
86%token FUN_WORD "$$word";
87%token FUN_BYTE "$$byte";
88%token FUN_LONG "$$long";
89
90/*
91%left "|";
92%left "^";
93%left "&";
94%left "==" "!=";
95%left ">>" "<<";
96%left "+" "-";
97%left "*" "/";
98*/
99
100%param { RezLexer& lexer }
101%param { RezWorld& world }
102
103%code requires {
104 #include "ResourceDefinitions.h"
105 #include "Expression.h"
106 #include "ResSpec.h"
107
108 #define YY_NULLPTR nullptr
109 class RezLexer;
110 class RezWorld;
111}
112
113%code provides {
114 using yy::RezParser;
115 //using RezSymbol = yy::RezParser::symbol_type;
116
117 class RezSymbol : public yy::RezParser::symbol_type
118 {
119 public:
120 RezSymbol() = default;
121 RezSymbol(yy::RezParser::symbol_type&& x) : yy::RezParser::symbol_type(std::move(x)) {}
122 };
123}
124
125%code {
126 #include "RezLexer.h"
127 #include "RezWorld.h"
128 #include "ResourceCompiler.h"
129 #include "Diagnostic.h"
130
131 static yy::RezParser::symbol_type yylex(RezLexer& lexer, RezWorld&)
132 {
133 return lexer.nextToken();
134 }
135
136 void yy::RezParser::error(const location_type& loc, std::string const& err)
137 {
138 world.problem(Diagnostic(Diagnostic::error, err, loc));
139 }
140
141 static std::string fromHex(std::string hex)
142 {
143 std::string bin;
144 int nibble;
145 bool haveNibble = false;
146 for(std::string::iterator p = hex.begin(); p != hex.end(); ++p)
147 {
148 if(std::isspace(*p))
149 continue;
150 assert(isdigit(*p) || (tolower(*p) >= 'a' && tolower(*p) <= 'f'));
151 int digit;
152 if(isdigit(*p))
153 digit = *p - '0';
154 else
155 digit = tolower(*p) - 'a' + 0xA;
156
157 if(haveNibble)
158 {
159 bin += (char) ((nibble << 4) | digit);
160 haveNibble = false;
161 }
162 else
163 {
164 nibble = digit;
165 haveNibble = true;
166 }
167 }
168 return bin;
169 }
170
171}
172
173%%
174%start rez;
175
176rez : %empty
177 | rez type_definition ";"
178 | rez resource ";"
179 | rez data ";"
180 ;
181
182type_definition : "type" type_spec
183 {
184 TypeDefinitionPtr td = std::make_shared<TypeDefinition>();
185 world.addTypeDefinition($type_spec, td);
186 world.fieldLists.push(td);
187 }
188 "{" field_definitions "}"
189 { world.fieldLists.pop(); if(world.verboseFlag) std::cout << "TYPE " << $2 << std::endl; }
190 | "type" type_spec "as" type_spec
191 {
192 if(world.verboseFlag) std::cout << "TYPE " << $2 << std::endl;
193 auto spec = $4;
194 world.addTypeDefinition($2, world.getTypeDefinition(spec.getType(), spec.getID(), @4));
195 }
196 ;
197
198%type <ResType> res_type;
199res_type : CHARLIT { $$ = ResType($1); } ;
200
201%type <TypeSpec> type_spec;
202type_spec : res_type { $$ = TypeSpec($res_type); }
203 | res_type "(" INTLIT ")" { $$ = TypeSpec($res_type, $INTLIT); }
204 ;
205
206field_definitions : %empty
207 | field_definitions IDENTIFIER ":" { world.fieldLists.top()->addLabel($2, @2); }
208 | field_definitions ";"
209 | field_definitions field_definition ";" { world.fieldLists.top()->addField($2, @2); }
210 ;
211
212%type <FieldPtr> field_definition;
213field_definition: simple_field_definition { $$ = $1; }
214 | array_definition { $$ = $1; }
215 | switch_definition { $$ = $1; }
216 | fill_statement { $$ = $1; }
217 | align_statement { $$ = $1; }
218 ;
219
220%type <SimpleFieldPtr> simple_field_definition;
221simple_field_definition: field_attributes simpletype array_count_opt value_spec_opt
222 {
223 $$ = std::make_shared<SimpleField>();
224 $$->attrs = $field_attributes;
225 $$->type = $simpletype;
226 $$->arrayCount = $array_count_opt;
227 $$->value = $value_spec_opt;
228 }
229 | simple_field_definition IDENTIFIER
230 { $$ = $1; $$->addNamedValue($IDENTIFIER); }
231 | simple_field_definition IDENTIFIER "=" value
232 { $$ = $1; $$->addNamedValue($IDENTIFIER, $value); }
233 | simple_field_definition "," IDENTIFIER
234 { $$ = $1; $$->addNamedValue($IDENTIFIER); }
235 | simple_field_definition "," IDENTIFIER "=" value
236 { $$ = $1; $$->addNamedValue($IDENTIFIER, $value); }
237 ;
238
239%type <ExprPtr> array_count array_count_opt value_spec_opt value resource_item;
240%type <ExprPtr> expression expression1 expression2 ;
241%type <ExprPtr> expression3 expression4 expression5 ;
242%type <ExprPtr> expression6 expression7 expression8;
243
244value_spec_opt : %empty { $$ = nullptr; } | "=" value { $$ = $2; } ;
245
246%type <SimpleField::Type> simpletype;
247simpletype : "boolean" { $$ = SimpleField::Type::boolean; }
248 | "byte" { $$ = SimpleField::Type::byte; }
249 | "integer" { $$ = SimpleField::Type::integer; }
250 | "longint" { $$ = SimpleField::Type::longint; }
251 | "rect" { $$ = SimpleField::Type::rect; }
252 | "point" { $$ = SimpleField::Type::point; }
253 | "char" { $$ = SimpleField::Type::char_; }
254 | "pstring" { $$ = SimpleField::Type::pstring; }
255 | "wstring" { $$ = SimpleField::Type::wstring; }
256 | "string" { $$ = SimpleField::Type::string; }
257 | "bitstring" { $$ = SimpleField::Type::bitstring; }
258 ;
259
260%type <FieldPtr> fill_statement align_statement;
261fill_statement : "fill" fill_unit array_count_opt
262 { $$ = std::make_shared<FillAlignField>($fill_unit, false, $array_count_opt); }
263 ;
264align_statement : "align" fill_unit
265 { $$ = std::make_shared<FillAlignField>($fill_unit, true); }
266 ;
267
268%type <FillAlignField::Type> fill_unit;
269fill_unit : "bit" { $$ = FillAlignField::Type::bit; }
270 | "nibble" { $$ = FillAlignField::Type::nibble; }
271 | "byte" { $$ = FillAlignField::Type::byte; }
272 | "word" { $$ = FillAlignField::Type::word; }
273 | "long" { $$ = FillAlignField::Type::long_; }
274 ;
275
276%type <FieldPtr> array_definition;
277array_definition:
278 array_attributes "array" array_name_opt array_count_opt
279 {
280 ArrayFieldPtr af = std::make_shared<ArrayField>($array_name_opt, $array_count_opt);
281 world.fieldLists.push(af);
282 }
283 "{" field_definitions "}"
284 {
285 $$ = world.fieldLists.top();
286 world.fieldLists.pop();
287 }
288 ;
289
290array_count : "[" expression "]" { $$ = $2; }
291array_count_opt : %empty { $$ = nullptr; } | array_count { $$ = $1; };
292
293%type <std::string> array_name_opt;
294array_name_opt : %empty { $$ = ""; } | IDENTIFIER { $$ = $1; } ;
295
296array_attributes: %empty | "wide" ;
297
298%type <SimpleField::Attrs> field_attributes field_attribute;
299field_attributes: %empty { $$ = SimpleField::Attrs::none; }
300 | field_attributes field_attribute { $$ = $1 | $2; }
301 ;
302
303field_attribute : "hex" { $$ = SimpleField::Attrs::hex; }
304 | "key" { $$ = SimpleField::Attrs::key; }
305 | "unsigned" { $$ = SimpleField::Attrs::unsigned_; }
306 | "literal" { $$ = SimpleField::Attrs::literal; }
307 | "binary" { $$ = SimpleField::Attrs::binary; }
308 ;
309
310%type <FieldPtr> switch_definition;
311switch_definition:
312 "switch"
313 { world.switches.push(std::make_shared<SwitchField>()); }
314 "{"
315 switch_cases
316 "}"
317 {
318 $$ = world.switches.top();
319 world.switches.pop();
320 }
321 ;
322
323switch_cases : %empty | switch_cases switch_case ;
324
325switch_case : "case" IDENTIFIER ":"
326 {
327 world.fieldLists.push(std::make_shared<FieldList>());
328 }
329 field_definitions
330 {
331 world.switches.top()->addCase($IDENTIFIER, world.fieldLists.top());
332 world.fieldLists.pop();
333 }
334 ;
335
336
337value : expression { $$ = $1; }
338 | "{" resource_body "}" { $$ = $2; }
339 | string_expression { $$ = $1; }
340 ;
341
342expression : expression1 { $$ = $1; }
343 | expression "^" expression1 { $$ = std::make_shared<BinaryExpr>(BinaryOp::XOR, $1, $3, @1); }
344 ;
345
346expression1 : expression2 { $$ = $1; }
347 | expression1 "&" expression2 { $$ = std::make_shared<BinaryExpr>(BinaryOp::AND, $1, $3, @1); }
348 ;
349
350expression2 : expression3 { $$ = $1; }
351 | expression2 "|" expression3 { $$ = std::make_shared<BinaryExpr>(BinaryOp::OR, $1, $3, @1); }
352 ;
353
354expression3 : expression4 { $$ = $1; }
355 | expression3 "==" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::EQUAL, $1, $3, @1); }
356 | expression3 "!=" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::NOTEQUAL, $1, $3, @1); }
357 ;
358
359expression4 : expression5 { $$ = $1; }
360 | expression4 ">>" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTRIGHT, $1, $3, @1); }
361 | expression4 "<<" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTLEFT, $1, $3, @1); }
362 ;
363
364expression5 : expression6 { $$ = $1; }
365 | expression5 "+" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::PLUS, $1, $3, @1); }
366 | expression5 "-" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MINUS, $1, $3, @1); }
367 ;
368
369expression6 : expression7 { $$ = $1; }
370 | expression6 "*" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MULTIPLY, $1, $3, @1); }
371 | expression6 "/" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::DIVIDE, $1, $3, @1); }
372 ;
373expression7 : expression8 { $$ = $1; }
374 | "-" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::MINUS, $2, @1); }
375 | "+" expression7 { $$ = $2; }
376 | "~" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::COMPLEMENT, $2, @1); }
377 ;
378
379expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1, @1); }
380 | CHARLIT { $$ = std::make_shared<IntExpr>($1, @1); }
381
382 | identifier_expression { $$ = $1; }
383 | "(" expression ")" { $$ = $2; }
384
385 | "$$countof" "(" identifier_expression ")"
386 { $$ = std::make_shared<CountOfExpr>($identifier_expression, @1); }
387 | "$$arrayindex" "(" identifier_expression ")"
388 { $$ = std::make_shared<ArrayIndexExpr>($identifier_expression, @1); }
389 | "$$bitfield" "(" expression "," expression "," expression ")"
390 { $$ = std::make_shared<PeekExpr>($3, $5, $7, @1); }
391 | "$$word" "(" expression ")"
392 { $$ = std::make_shared<PeekExpr>($3, 16, @1); }
393 | "$$byte" "(" expression ")"
394 { $$ = std::make_shared<PeekExpr>($3, 8, @1); }
395 | "$$long" "(" expression ")"
396 { $$ = std::make_shared<PeekExpr>($3, 32, @1); }
397 ;
398
399%type <IdentifierExprPtr> identifier_expression;
400identifier_expression : IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1, @1); }
401 | IDENTIFIER
402 { world.functionCalls.push(std::make_shared<IdentifierExpr>($1, @1)); }
403 "[" function_argument_list1 "]"
404 { $$ = world.functionCalls.top(); world.functionCalls.pop(); }
405 ;
406
407function_argument_list : %empty | function_argument_list1 ;
408function_argument_list1 : expression
409 { world.functionCalls.top()->addArgument($expression); }
410 | function_argument_list "," expression
411 { world.functionCalls.top()->addArgument($expression); }
412 ;
413
414%type <ExprPtr> string_expression string_expression1;
415string_expression : string_expression1 { $$ = $1; }
416 | string_expression string_expression1
417 { $$ = std::make_shared<BinaryExpr>(BinaryOp::CONCAT, $1, $2, @1); }
418 ;
419
420%type <std::string> stringlit;
421stringlit : STRINGLIT { $$ = $1; }
422 | DOLLAR STRINGLIT { $$ = fromHex($2); }
423 ;
424
425string_expression1 : stringlit { $$ = std::make_shared<StringExpr>($1, @1); }
426 | "$$read" "(" string_expression ")"
427 { $$ = std::make_shared<ReadExpr>($string_expression, @1); }
428 ;
429
430resource : "resource" res_spec "{" resource_body "}"
431 {
432 world.addResource($res_spec, $resource_body, @1);
433 }
434 ;
435
436%type <ResSpec> res_spec;
437%type <ResSpec> resource_attributes;
438
439res_spec : res_type "(" expression resource_attributes ")"
440 {
441 $$ = $resource_attributes;
442 $$.type() = $res_type;
443 $$.id() = $expression->evaluateInt(nullptr);
444 }
445 ;
446
447resource_attributes : %empty { $$ = ResSpec(); }
448 | resource_attributes "," IDENTIFIER
449 {
450 $$ = $1;
451 if($IDENTIFIER == "changed")
452 $$.attr() |= 2;
453 else if($IDENTIFIER == "preload")
454 $$.attr() |= 4;
455 else if($IDENTIFIER == "protected")
456 $$.attr() |= 8;
457 else if($IDENTIFIER == "locked")
458 $$.attr() |= 16;
459 else if($IDENTIFIER == "purgeable")
460 $$.attr() |= 32;
461 else if($IDENTIFIER == "sysheap")
462 $$.attr() |= 64;
463 else if($IDENTIFIER == "unchanged")
464 $$.attr() &= ~2;
465 else if($IDENTIFIER == "nonpreload")
466 $$.attr() &= ~4;
467 else if($IDENTIFIER == "unprotected")
468 $$.attr() &= ~8;
469 else if($IDENTIFIER == "unlocked")
470 $$.attr() &= ~16;
471 else if($IDENTIFIER == "nonpurgeable")
472 $$.attr() &= ~32;
473 else if($IDENTIFIER == "appheap")
474 $$.attr() &= ~64;
475 else
476 world.problem(Diagnostic(Diagnostic::error, "illegal attribute " + $IDENTIFIER, @1));
477 }
478 | resource_attributes "," string_expression
479 {
480 $$ = $1;
481 $$.name() = $3->evaluateString(nullptr);
482 }
483 ;
484
485
486
487%type <CompoundExprPtr> resource_body resource_body1;
488resource_body : %empty { $$ = std::make_shared<CompoundExpr>(yy::location()); }
489 | resource_body1 { $$ = $1; $$->location = @1; }
490 ;
491resource_body1 : resource_item { $$ = std::make_shared<CompoundExpr>(@1); $$->addItem($1); }
492 | resource_body1 "," resource_item { $$ = $1; $$->addItem($3); }
493 | resource_body1 ";" resource_item { $$ = $1; $$->addItem($3); }
494 | resource_body1 ";" { $$ = $1; }
495 | resource_body1 "," { $$ = $1; }
496 ;
497
498resource_item : value { $$ = $1; }
499 | IDENTIFIER "{" resource_body "}" { $$ = std::make_shared<CaseExpr>($IDENTIFIER, $resource_body, @1); }
500 ;
501
502
503data : "data" res_spec "{" string_expression "}"
504{
505 world.addData($res_spec, $string_expression->evaluateString(nullptr), @1);
506}
507;
508
509%%