Retro68/Rez/RezParser.yy

374 lines
11 KiB
Plaintext
Raw Normal View History

2014-10-05 21:52:34 +00:00
%require "3.0.2"
%defines
%define parser_class_name {RezParser}
%skeleton "lalr1.cc"
%locations;
%define api.token.constructor
%define api.value.type variant
%define parse.assert
%token<std::string> IDENTIFIER;
2014-10-06 15:03:25 +00:00
%token<int> CHARLIT;
2014-10-05 21:52:34 +00:00
%token<std::string> STRINGLIT;
%token<int> INTLIT;
%token<std::string> BADTOKEN;
%token LEFTBRACE "{";
%token RIGHTBRACE "}";
%token LEFTBRACKET "[";
%token RIGHTBRACKET "]";
%token LEFTPAREN "(";
%token RIGHTPAREN ")";
%token SEMICOLON ";";
%token COMMA ",";
%token PLUS "+";
%token MINUS "-";
%token DIVIDE "/";
%token STAR "*";
%token ASSIGN "=";
%token COLON ":";
%token SHIFTLEFT "<<";
%token SHIFTRIGHT ">>";
%token EQUAL "==";
%token NOTEQUAL "!=";
%token AND "&";
%token OR "|";
%token XOR "^";
%token COMPL "~";
%token TYPE "type";
%token RESOURCE "resource";
%token ARRAY "array";
%token SWITCH "switch";
%token CASE "case";
%token AS "as";
%token FILL "fill";
%token ALIGN "align";
%token HEX "hex";
%token KEY "key";
%token WIDE "wide";
%token LITERAL "literal";
%token UNSIGNED "unsigned";
%token BOOLEAN "boolean";
%token BIT "bit";
2014-10-07 23:37:28 +00:00
%token NIBBLE "nibble";
2014-10-05 21:52:34 +00:00
%token BYTE "byte";
%token CHAR "char";
%token WORD "word";
%token INTEGER "integer";
%token LONG "long";
%token LONGINT "longint";
%token PSTRING "pstring";
%token WSTRING "wstring";
%token STRING "string";
%token POINT "point";
%token RECT "rect";
%token BITSTRING "bitstring";
/*
%left "|";
%left "^";
%left "&";
%left "==" "!=";
%left ">>" "<<";
%left "+" "-";
%left "*" "/";
*/
%param { RezLexer& lexer }
%param { RezWorld& world }
2014-10-05 21:52:34 +00:00
%code requires {
2014-10-06 15:03:25 +00:00
#include "ResourceDefinitions.h"
#include "Expression.h"
2014-10-06 15:03:25 +00:00
2014-10-05 21:52:34 +00:00
#define YY_NULLPTR nullptr
class RezLexer;
class RezWorld;
2014-10-05 21:52:34 +00:00
}
%code provides {
using yy::RezParser;
//using RezSymbol = yy::RezParser::symbol_type;
class RezSymbol : public yy::RezParser::symbol_type
{
public:
RezSymbol() = default;
RezSymbol(const yy::RezParser::symbol_type& x) : yy::RezParser::symbol_type(x) {}
};
}
%code {
#include "RezLexer.h"
#include "RezWorld.h"
#include "ResourceCompiler.h"
static yy::RezParser::symbol_type yylex(RezLexer& lexer, RezWorld&)
2014-10-05 21:52:34 +00:00
{
return lexer.nextToken();
}
void yy::RezParser::error(const location_type& loc, std::string const& err)
{
std::cerr << loc << ": " << err << std::endl;
}
}
%%
%start rez;
rez : %empty
| rez type_definition ";"
| rez resource ";"
;
type_definition : "type" type_spec
{
TypeDefinitionPtr td = std::make_shared<TypeDefinition>();
world.addTypeDefinition($type_spec, td);
world.fieldLists.push(td);
}
"{" field_definitions "}"
{ world.fieldLists.pop(); std::cout << "TYPE " << $2 << std::endl; }
2014-10-05 21:52:34 +00:00
| "type" type_spec "as" type_spec
{ std::cout << "TYPE " << $2 << std::endl; }
;
2014-10-06 15:03:25 +00:00
%type <ResType> res_type;
res_type : CHARLIT { $$ = ResType($1); } ;
%type <TypeSpec> type_spec;
type_spec : res_type { $$ = TypeSpec($res_type); }
| res_type "(" INTLIT ")" { $$ = TypeSpec($res_type, $INTLIT); }
2014-10-05 21:52:34 +00:00
;
field_definitions : %empty
| field_definitions IDENTIFIER ":" { world.fieldLists.top()->addLabel($2); }
2014-10-05 21:52:34 +00:00
| field_definitions ";"
| field_definitions field_definition ";" { world.fieldLists.top()->addField($2); }
;
2014-10-05 21:52:34 +00:00
2014-10-06 15:03:25 +00:00
%type <FieldPtr> field_definition;
field_definition: simple_field_definition { $$ = $1; }
2014-10-07 18:44:40 +00:00
| array_definition { $$ = $1; }
2014-10-07 23:17:17 +00:00
| switch_definition { $$ = $1; }
2014-10-07 23:37:28 +00:00
| fill_statement { $$ = $1; }
| align_statement { $$ = $1; }
;
2014-10-05 21:52:34 +00:00
2014-10-06 15:03:25 +00:00
%type <SimpleFieldPtr> simple_field_definition;
simple_field_definition: field_attributes simpletype array_count_opt value_spec_opt
{
$$ = std::make_shared<SimpleField>();
$$->attrs = $field_attributes;
$$->type = $simpletype;
$$->arrayCount = $array_count_opt;
$$->value = $value_spec_opt;
}
| simple_field_definition IDENTIFIER
{ $$ = $1; $$->addNamedValue($IDENTIFIER); }
| simple_field_definition IDENTIFIER "=" value
{ $$ = $1; $$->addNamedValue($IDENTIFIER, $value); }
| simple_field_definition "," IDENTIFIER
{ $$ = $1; $$->addNamedValue($IDENTIFIER); }
| simple_field_definition "," IDENTIFIER "=" value
{ $$ = $1; $$->addNamedValue($IDENTIFIER, $value); }
;
%type <ExprPtr> array_count array_count_opt value_spec_opt value resource_item;
2014-10-06 15:03:25 +00:00
%type <ExprPtr> expression expression1 expression2 ;
%type <ExprPtr> expression3 expression4 expression5 ;
%type <ExprPtr> expression6 expression7 expression8;
2014-10-06 15:03:25 +00:00
value_spec_opt : %empty { $$ = nullptr; } | "=" value { $$ = $2; } ;
%type <SimpleField::Type> simpletype;
simpletype : "boolean" { $$ = SimpleField::Type::boolean; }
| "byte" { $$ = SimpleField::Type::byte; }
| "integer" { $$ = SimpleField::Type::integer; }
| "longint" { $$ = SimpleField::Type::longint; }
| "rect" { $$ = SimpleField::Type::rect; }
| "point" { $$ = SimpleField::Type::point; }
| "char" { $$ = SimpleField::Type::char_; }
| "pstring" { $$ = SimpleField::Type::pstring; }
| "wstring" { $$ = SimpleField::Type::wstring; }
| "string" { $$ = SimpleField::Type::string; }
| "bitstring" { $$ = SimpleField::Type::bitstring; }
;
2014-10-07 23:37:28 +00:00
%type <FieldPtr> fill_statement align_statement;
fill_statement : "fill" fill_unit array_count_opt
{ $$ = std::make_shared<FillAlignField>($fill_unit, false, $array_count_opt); }
;
align_statement : "align" fill_unit
{ $$ = std::make_shared<FillAlignField>($fill_unit, true); }
;
2014-10-05 21:52:34 +00:00
2014-10-07 23:37:28 +00:00
%type <FillAlignField::Type> fill_unit;
fill_unit : "bit" { $$ = FillAlignField::Type::bit; }
| "nibble" { $$ = FillAlignField::Type::nibble; }
| "byte" { $$ = FillAlignField::Type::byte; }
| "word" { $$ = FillAlignField::Type::word; }
| "long" { $$ = FillAlignField::Type::long_; }
;
2014-10-05 21:52:34 +00:00
2014-10-07 18:44:40 +00:00
%type <FieldPtr> array_definition;
array_definition:
array_attributes "array" array_name_opt array_count_opt
{
ArrayFieldPtr af = std::make_shared<ArrayField>($array_name_opt, $array_count_opt);
world.fieldLists.push(af);
}
"{" field_definitions "}"
{
$$ = world.fieldLists.top();
world.fieldLists.pop();
}
;
2014-10-05 21:52:34 +00:00
2014-10-06 15:03:25 +00:00
array_count : "[" expression "]" { $$ = $2; }
2014-10-07 18:44:40 +00:00
array_count_opt : %empty { $$ = nullptr; } | array_count { $$ = $1; };
2014-10-05 21:52:34 +00:00
2014-10-07 18:44:40 +00:00
%type <std::string> array_name_opt;
array_name_opt : %empty { $$ = ""; } | IDENTIFIER { $$ = $1; } ;
2014-10-05 21:52:34 +00:00
array_attributes: %empty | "wide" ;
2014-10-06 15:03:25 +00:00
%type <SimpleField::Attrs> field_attributes field_attribute;
field_attributes: %empty { $$ = SimpleField::Attrs::none; }
| field_attributes field_attribute { $$ = $1 | $2; }
;
field_attribute : "hex" { $$ = SimpleField::Attrs::hex; }
| "key" { $$ = SimpleField::Attrs::key; }
| "unsigned" { $$ = SimpleField::Attrs::unsigned_; }
| "literal" { $$ = SimpleField::Attrs::literal; }
;
2014-10-05 21:52:34 +00:00
2014-10-07 23:17:17 +00:00
%type <FieldPtr> switch_definition;
switch_definition:
"switch"
{ world.switches.push(std::make_shared<SwitchField>()); }
"{"
2014-10-05 21:52:34 +00:00
switch_cases
2014-10-07 23:17:17 +00:00
"}"
{
$$ = world.switches.top();
world.switches.pop();
}
;
2014-10-05 21:52:34 +00:00
switch_cases : %empty | switch_cases switch_case ;
2014-10-07 23:17:17 +00:00
switch_case : "case" IDENTIFIER ":"
{
world.fieldLists.push(std::make_shared<FieldList>());
}
field_definitions
{
world.switches.top()->addCase($IDENTIFIER, world.fieldLists.top());
world.fieldLists.pop();
}
;
2014-10-05 21:52:34 +00:00
value : expression { $$ = $1; }
| "{" resource_body "}" { $$ = $2; }
2014-10-06 15:03:25 +00:00
| STRINGLIT { $$ = std::make_shared<StringExpr>($1); }
;
expression : expression1 { $$ = $1; }
| expression "^" expression1 { $$ = std::make_shared<BinaryExpr>(BinaryOp::XOR, $1, $3); }
2014-10-05 21:52:34 +00:00
;
expression1 : expression2 { $$ = $1; }
| expression1 "&" expression2 { $$ = std::make_shared<BinaryExpr>(BinaryOp::AND, $1, $3); }
2014-10-05 21:52:34 +00:00
;
expression2 : expression3 { $$ = $1; }
| expression2 "|" expression3 { $$ = std::make_shared<BinaryExpr>(BinaryOp::OR, $1, $3); }
2014-10-05 21:52:34 +00:00
;
expression3 : expression4 { $$ = $1; }
| expression3 "==" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::EQUAL, $1, $3); }
| expression3 "!=" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::NOTEQUAL, $1, $3); }
2014-10-05 21:52:34 +00:00
;
expression4 : expression5 { $$ = $1; }
| expression4 ">>" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTRIGHT, $1, $3); }
| expression4 "<<" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTLEFT, $1, $3); }
2014-10-05 21:52:34 +00:00
;
expression5 : expression6 { $$ = $1; }
| expression5 "+" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::PLUS, $1, $3); }
| expression5 "-" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MINUS, $1, $3); }
2014-10-05 21:52:34 +00:00
;
expression6 : expression7 { $$ = $1; }
| expression6 "*" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MULTIPLY, $1, $3); }
| expression6 "/" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::DIVIDE, $1, $3); }
2014-10-05 21:52:34 +00:00
;
expression7 : expression8 { $$ = $1; }
| "-" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::MINUS, $2); }
| "+" expression7 { $$ = $2; }
| "~" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::COMPLEMENT, $2); }
2014-10-05 21:52:34 +00:00
;
2014-10-06 15:03:25 +00:00
expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1); }
| CHARLIT { $$ = std::make_shared<IntExpr>($1); }
2014-10-07 22:41:40 +00:00
| IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1); }
| IDENTIFIER
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1,true)); }
"(" function_argument_list ")"
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); }
| IDENTIFIER
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1,false)); }
"[" function_argument_list1 "]"
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); }
2014-10-06 15:03:25 +00:00
| "(" expression ")" { $$ = $2; }
2014-10-05 21:52:34 +00:00
;
function_argument_list : %empty | function_argument_list1 ;
2014-10-07 22:41:40 +00:00
function_argument_list1 : expression
{ world.functionCalls.top()->addArgument($expression); }
| function_argument_list "," expression
{ world.functionCalls.top()->addArgument($expression); }
;
2014-10-05 21:52:34 +00:00
resource : "resource" res_type "(" expression resource_attributes ")" "{" resource_body "}"
{
int id = $expression->evaluateInt(nullptr);
2014-10-08 00:52:34 +00:00
world.addResource($res_type, id, $resource_body);
}
;
%type <int> resource_attributes resource_attribute;
resource_attributes : %empty { $$ = 0; }
| resource_attributes "," resource_attribute { $$ = $1 | $3; }
;
resource_attribute : IDENTIFIER { $$ = 0; } /* ### */
2014-10-05 21:52:34 +00:00
%type <CompoundExprPtr> resource_body resource_body1;
resource_body : %empty { $$ = std::make_shared<CompoundExpr>(); }
| resource_body1 { $$ = $1; }
;
resource_body1 : resource_item { $$ = std::make_shared<CompoundExpr>(); $$->addItem($1); }
| resource_body1 "," resource_item { $$ = $1; $$->addItem($3); }
| resource_body1 ";" resource_item { $$ = $1; $$->addItem($3); }
| resource_body1 ";" { $$ = $1; }
2014-10-05 21:52:34 +00:00
;
resource_item : value { $$ = $1; }
2014-10-07 23:17:17 +00:00
| IDENTIFIER "{" resource_body "}" { $$ = std::make_shared<CaseExpr>($IDENTIFIER, $resource_body); }
;
2014-10-05 21:52:34 +00:00
%%