diff --git a/README.md b/README.md index fce6852e..ac75db82 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,13 @@ A utility to compile & decompile IW engine game scripts. - **IW8** *(Call of Duty: Modern Warfare (2019))* - **S1** *(Call of Duty: Advanced Warfare)* - **S2** *(Call of Duty: WWII)* +- **S4** *(Call of Duty: Vanguard)* - **H1** *(Call of Duty: Modern Warfare Remastered)* - **H2** *(Call of Duty: Modern Warfare 2 Campaign Remastered)* ## Usage ``./gsc-tool.exe `` -**game**: `-iw5`, `-iw6`, `-iw7`, `-iw8`, `-s1`, `-s2`, `-h1`, `-h2` +**game**: `-iw5`, `-iw6`, `-iw7`, `-iw8`, `-s1`, `-s2`, `-s4`, `-h1`, `-h2` | Mode |Description | Output | |:---------|:--------------------------|:------------| |`-asm` |assemble a `file.gscasm` |`file.gscbin`| diff --git a/gen/iw8/Makefile b/gen/iw8/Makefile index 7e036f24..3140c314 100644 --- a/gen/iw8/Makefile +++ b/gen/iw8/Makefile @@ -1,4 +1,4 @@ -generate: S2 +generate: IW8 clean: rm -rf ./parser.hpp @@ -6,6 +6,6 @@ clean: rm -rf ./lexer.hpp rm -rf ./lexer.cpp -S2: lexer.lpp parser.ypp +IW8: lexer.lpp parser.ypp flex lexer.lpp bison parser.ypp -Wcounterexamples diff --git a/gen/s4/Makefile b/gen/s4/Makefile new file mode 100644 index 00000000..b3f80218 --- /dev/null +++ b/gen/s4/Makefile @@ -0,0 +1,11 @@ +generate: S4 + +clean: + rm -rf ./parser.hpp + rm -rf ./parser.cpp + rm -rf ./lexer.hpp + rm -rf ./lexer.cpp + +S4: lexer.lpp parser.ypp + flex lexer.lpp + bison parser.ypp -Wcounterexamples diff --git a/gen/s4/lexer.lpp b/gen/s4/lexer.lpp new file mode 100644 index 00000000..53190282 --- /dev/null +++ b/gen/s4/lexer.lpp @@ -0,0 +1,154 @@ +/* Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. +*/ + +%option outfile="lexer.cpp" +%option header-file="lexer.hpp" +%option prefix="s4_" +%option reentrant +%option noyywrap batch nounput noinput +%option never-interactive +%option nounistd + +%top{ +#include "stdafx.hpp" +#include "s4.hpp" +#include "parser.hpp" +using namespace xsk::gsc; +} + +%{ +#define YY_USER_ACTION loc.columns(yyleng); +%} + +RGX_FILE ([_A-Za-z0-9]+\\)+[_A-Za-z0-9]+ +RGX_NAME [_A-Za-z][_A-Za-z0-9]* +RGX_STRING \"(?:\\.|[^\"])*?\"|\'(?:\\.|[^\'])*?\' +RGX_COLOR #([0-9a-fA-F]{6}|[0-9a-fA-F]{3}) +RGX_FLT_DEC [0-9]+\.(?:[0-9]*)?f?|\.[0-9]+f? +RGX_INT_OCT 0[1-7][0-7]* +RGX_INT_BIN 0[bB][01]+ +RGX_INT_HEX 0[xX][0-9a-fA-F]+ +RGX_INT_DEC [0-9]+ +RGX_DEFAULT (.|\n) + +%x COMMENT_BLOCK_STATE +%x DEVELOPER_BLOCK_STATE + +%% + +%{ + loc.step(); +%} + +[ \t\r] { loc.step(); } + +\n { loc.lines(yyleng); loc.step(); } + +"//".* + +"/*" { BEGIN(COMMENT_BLOCK_STATE); } +. +\n { loc.lines(yyleng); loc.step(); } +"*/" { BEGIN(INITIAL); } + +"/#" { BEGIN(DEVELOPER_BLOCK_STATE); } +. +\n { loc.lines(yyleng); loc.step(); } +"#/" { BEGIN(INITIAL); } + +"#include" { return s4::parser::make_INCLUDE(loc); } +"#using_animtree" { return s4::parser::make_USINGTREE(loc); } +"#animtree" { return s4::parser::make_ANIMTREE(loc); } +"endon" { return s4::parser::make_ENDON(loc); } +"notify" { return s4::parser::make_NOTIFY(loc); } +"wait" { return s4::parser::make_WAIT(loc); } +"waittill" { return s4::parser::make_WAITTILL(loc); } +"waittillmatch" { return s4::parser::make_WAITTILLMATCH(loc); } +"waittillframeend" { return s4::parser::make_WAITTILLFRAMEEND(loc); } +"waitframe" { return s4::parser::make_WAITFRAME(loc); } +"if" { return s4::parser::make_IF(loc); } +"else" { return s4::parser::make_ELSE(loc); } +"while" { return s4::parser::make_WHILE(loc); } +"for" { return s4::parser::make_FOR(loc); } +"foreach" { return s4::parser::make_FOREACH(loc); } +"in" { return s4::parser::make_IN(loc); } +"switch" { return s4::parser::make_SWITCH(loc); } +"case" { return s4::parser::make_CASE(loc); } +"default" { return s4::parser::make_DEFAULT(loc); } +"break" { return s4::parser::make_BREAK(loc); } +"continue" { return s4::parser::make_CONTINUE(loc); } +"return" { return s4::parser::make_RETURN(loc); } +"thread" { return s4::parser::make_THREAD(loc); } +"childthread" { return s4::parser::make_CHILDTHREAD(loc); } +"thisthread" { return s4::parser::make_THISTHREAD(loc); } +"call" { return s4::parser::make_CALL(loc); } +"true" { return s4::parser::make_TRUE(loc); } +"false" { return s4::parser::make_FALSE(loc); } +"undefined" { return s4::parser::make_UNDEFINED(loc); } +"size" { return s4::parser::make_SIZE(loc); } +"game" { return s4::parser::make_GAME(loc); } +"self" { return s4::parser::make_SELF(loc); } +"anim" { return s4::parser::make_ANIM(loc); } +"level" { return s4::parser::make_LEVEL(loc); } +\( { return s4::parser::make_LPAREN(loc); } +\) { return s4::parser::make_RPAREN(loc); } +\{ { return s4::parser::make_LBRACE(loc); } +\} { return s4::parser::make_RBRACE(loc); } +\[ { return s4::parser::make_LBRACKET(loc); } +\] { return s4::parser::make_RBRACKET(loc); } +\, { return s4::parser::make_COMMA(loc); } +\. { return s4::parser::make_DOT(loc); } +\:\: { return s4::parser::make_DOUBLECOLON(loc); } +\: { return s4::parser::make_COLON(loc); } +\; { return s4::parser::make_SEMICOLON(loc); } +\? { return s4::parser::make_QMARK(loc); } +\+\+ { return s4::parser::make_INCREMENT(loc); } +\-\- { return s4::parser::make_DECREMENT(loc); } +\<\<\= { return s4::parser::make_ASSIGN_LSHIFT(loc); } +\>\>\= { return s4::parser::make_ASSIGN_RSHIFT(loc); } +\<\< { return s4::parser::make_LSHIFT(loc); } +\>\> { return s4::parser::make_RSHIFT(loc); } +\|\| { return s4::parser::make_OR(loc); } +\&\& { return s4::parser::make_AND(loc); } +\=\= { return s4::parser::make_EQUALITY(loc); } +\!\= { return s4::parser::make_INEQUALITY(loc); } +\<\= { return s4::parser::make_LESS_EQUAL(loc); } +\>\= { return s4::parser::make_GREATER_EQUAL(loc); } +\< { return s4::parser::make_LESS(loc); } +\> { return s4::parser::make_GREATER(loc); } +\+\= { return s4::parser::make_ASSIGN_ADD(loc); } +\-\= { return s4::parser::make_ASSIGN_SUB(loc); } +\*\= { return s4::parser::make_ASSIGN_MULT(loc); } +\/\= { return s4::parser::make_ASSIGN_DIV(loc); } +\%\= { return s4::parser::make_ASSIGN_MOD(loc); } +\|\= { return s4::parser::make_ASSIGN_BITWISE_OR(loc); } +\&\= { return s4::parser::make_ASSIGN_BITWISE_AND(loc); } +\^\= { return s4::parser::make_ASSIGN_BITWISE_EXOR(loc); } +\= { return s4::parser::make_ASSIGN(loc); } +\+ { return s4::parser::make_ADD(loc); } +\- { return s4::parser::make_SUB(loc); } +\* { return s4::parser::make_MULT(loc); } +\/ { return s4::parser::make_DIV(loc); } +\% { return s4::parser::make_MOD(loc); } +\! { return s4::parser::make_NOT(loc); } +\~ { return s4::parser::make_COMPLEMENT(loc); } +\| { return s4::parser::make_BITWISE_OR(loc); } +\& { return s4::parser::make_BITWISE_AND(loc); } +\^ { return s4::parser::make_BITWISE_EXOR(loc); } +{RGX_FILE} { return s4::parser::make_FILE(utils::string::fordslash(yytext), loc); } +{RGX_NAME} { return s4::parser::make_NAME((std::string(yytext, 3) == "_ID") ? std::string(yytext) : utils::string::to_lower(yytext), loc); } +\&{RGX_STRING} { return s4::parser::make_ISTRING(std::string(yytext).substr(1), loc); } +{RGX_STRING} { return s4::parser::make_STRING(std::string(yytext), loc); } +{RGX_COLOR} { return s4::parser::make_COLOR(std::string(yytext).substr(1), loc); } +{RGX_FLT_DEC} { return s4::parser::make_FLOAT(std::string(yytext), loc); } +{RGX_INT_OCT} { return s4::parser::make_INT_OCT(utils::string::oct_to_dec(yytext), loc); } +{RGX_INT_BIN} { return s4::parser::make_INT_BIN(utils::string::bin_to_dec(yytext), loc); } +{RGX_INT_HEX} { return s4::parser::make_INT_HEX(utils::string::hex_to_dec(yytext), loc); } +{RGX_INT_DEC} { return s4::parser::make_INT_DEC(std::string(yytext), loc); } +<> { return s4::parser::make_S4EOF(loc); } +<*>{RGX_DEFAULT} { throw s4::parser::syntax_error(loc, "bad token: \'" + std::string(yytext) + "\'"); } + +%% diff --git a/gen/s4/parser.ypp b/gen/s4/parser.ypp new file mode 100644 index 00000000..e43a53b0 --- /dev/null +++ b/gen/s4/parser.ypp @@ -0,0 +1,663 @@ +/* Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. +*/ + +%require "3.7" +%skeleton "lalr1.cc" +%language "c++" +%output "parser.cpp" +%defines "parser.hpp" +%define api.prefix {S4} +%define api.namespace {xsk::gsc::s4} +%define api.location.type {xsk::gsc::location} +%define api.value.type variant +%define api.token.constructor +%define api.token.raw +%define parse.assert +%define parse.trace +%define parse.error detailed +%define parse.lac full + +%locations + +%lex-param { yyscan_t yyscanner } +%lex-param { xsk::gsc::location& loc } + +%parse-param { yyscan_t yyscanner } +%parse-param { xsk::gsc::location& loc } +%parse-param { xsk::gsc::program_ptr& ast } + +%code requires +{ +#include "s4.hpp" +typedef void *yyscan_t; +#define YY_DECL xsk::gsc::s4::parser::symbol_type S4lex(yyscan_t yyscanner, xsk::gsc::location& loc) +} + +%code top +{ +#include "stdafx.hpp" +#include "parser.hpp" +#include "lexer.hpp" +using namespace xsk::gsc; +xsk::gsc::s4::parser::symbol_type S4lex(yyscan_t yyscanner, xsk::gsc::location& loc); +} + +%token INCLUDE "#include" +%token USINGTREE "#using_animtree" +%token ANIMTREE "#animtree" +%token ENDON "endon" +%token NOTIFY "notify" +%token WAIT "wait" +%token WAITTILL "waittill" +%token WAITTILLMATCH "waittillmatch" +%token WAITTILLFRAMEEND "waittillframeend" +%token WAITFRAME "waitframe" +%token IF "if" +%token ELSE "else" +%token WHILE "while" +%token FOR "for" +%token FOREACH "foreach" +%token IN "in" +%token SWITCH "switch" +%token CASE "case" +%token DEFAULT "default" +%token BREAK "break" +%token CONTINUE "continue" +%token RETURN "return" +%token THREAD "thread" +%token CHILDTHREAD "childthread" +%token THISTHREAD "thisthread" +%token CALL "call" +%token TRUE "true" +%token FALSE "false" +%token UNDEFINED "undefined" +%token SIZE "size" +%token GAME "game" +%token SELF "self" +%token ANIM "anim" +%token LEVEL "level" +%token LPAREN "(" +%token RPAREN ")" +%token LBRACE "{" +%token RBRACE "}" +%token LBRACKET "[" +%token RBRACKET "]" +%token COMMA "," +%token DOT "." +%token DOUBLECOLON "::" +%token COLON ":" +%token SEMICOLON ";" +%token QMARK "?" +%token INCREMENT "++" +%token DECREMENT "--" +%token LSHIFT "<<" +%token RSHIFT ">>" +%token OR "||" +%token AND "&&" +%token EQUALITY "==" +%token INEQUALITY "!=" +%token LESS_EQUAL "<=" +%token GREATER_EQUAL ">=" +%token LESS "<" +%token GREATER ">" +%token NOT "!" +%token COMPLEMENT "~" +%token ASSIGN "=" +%token ASSIGN_ADD "+=" +%token ASSIGN_SUB "-=" +%token ASSIGN_MULT "*=" +%token ASSIGN_DIV "/=" +%token ASSIGN_MOD "%=" +%token ASSIGN_BITWISE_OR "|=" +%token ASSIGN_BITWISE_AND "&=" +%token ASSIGN_BITWISE_EXOR "^=" +%token ASSIGN_RSHIFT ">>=" +%token ASSIGN_LSHIFT "<<=" +%token BITWISE_OR "|" +%token BITWISE_AND "&" +%token BITWISE_EXOR "^" +%token ADD "+" +%token SUB "-" +%token MULT "*" +%token DIV "/" +%token MOD "%" +%token FILE "file path" +%token NAME "identifier" +%token STRING "string literal" +%token ISTRING "localized string" +%token COLOR "color" +%token FLOAT "float" +%token INT_DEC "int" +%token INT_OCT "octal int" +%token INT_BIN "binary int" +%token INT_HEX "hexadecimal int" + +%type program +%type include +%type define +%type usingtree +%type constant +%type thread +%type parameters +%type stmt +%type stmt_block +%type stmt_list +%type stmt_call +%type stmt_assign +%type stmt_endon +%type stmt_notify +%type stmt_wait +%type stmt_waittill +%type stmt_waittillmatch +%type stmt_waittillframeend +%type stmt_waitframe +%type stmt_if +%type stmt_ifelse +%type stmt_while +%type stmt_for +%type stmt_foreach +%type stmt_switch +%type stmt_case +%type stmt_default +%type stmt_break +%type stmt_continue +%type stmt_return +%type for_stmt +%type for_expr +%type expr_assign +%type expr +%type expr_compare +%type expr_ternary +%type expr_binary +%type expr_primitive +%type expr_call +%type expr_call_thread +%type expr_call_childthread +%type expr_call_function +%type expr_call_pointer +%type expr_arguments +%type expr_arguments_filled +%type expr_arguments_empty +%type expr_function +%type expr_add_array +%type expr_array +%type expr_field +%type expr_size +%type object +%type thisthread +%type empty_array +%type undefined +%type game +%type self +%type anim +%type level +%type animation +%type animtree +%type name +%type file +%type istring +%type string +%type color +%type vector +%type float +%type integer +%type false +%type true + +%nonassoc ADD_ARRAY +%nonassoc RBRACKET +%nonassoc THEN +%nonassoc ELSE +%nonassoc INCREMENT DECREMENT + +%precedence TERN +%right QMARK +%left OR +%left AND +%left BITWISE_OR +%left BITWISE_AND +%left BITWISE_EXOR +%left EQUALITY INEQUALITY +%left LESS GREATER LESS_EQUAL GREATER_EQUAL +%left LSHIFT RSHIFT +%left ADD SUB +%left MULT DIV MOD +%right NOT COMPLEMENT + +%precedence NEG +%precedence ANIMREF +%precedence PREINC PREDEC +%precedence POSTINC POSTDEC + +%start root + +%% + +root + : program { ast = std::move($1); } + | { ast = std::make_unique(@$); } + ; + +program + : program include + { $$ = std::move($1); $$->includes.push_back(std::move($2)); } + | program define + { $$ = std::move($1); $$->definitions.push_back(std::move($2)); } + | include + { $$ = std::make_unique(@$); $$->includes.push_back(std::move($1)); } + | define + { $$ = std::make_unique(@$); $$->definitions.push_back(std::move($1)); } + ; + +include + : INCLUDE file SEMICOLON + { $$ = std::make_unique(@$, std::move($2)); } + ; + +define + : usingtree { $$.as_usingtree = std::move($1); } + | constant { $$.as_constant = std::move($1); } + | thread { $$.as_thread = std::move($1); } + ; + +usingtree + : USINGTREE LPAREN string RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($3)); } + ; + +constant + : name ASSIGN expr SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +thread + : name LPAREN parameters RPAREN stmt_block + { $$ = std::make_unique(@$, std::move($1), std::move($3), std::move($5)); } + ; + +parameters + : parameters COMMA name + { $$ = std::move($1); $$->list.push_back(std::move($3)); } + | name + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + | + { $$ = std::make_unique(@$); } + ; + +stmt + : stmt_block { $$.as_list = std::move($1); } + | stmt_call { $$.as_call = std::move($1); } + | stmt_assign { $$.as_assign = std::move($1); } + | stmt_endon { $$.as_endon = std::move($1); } + | stmt_notify { $$.as_notify = std::move($1); } + | stmt_wait { $$.as_wait = std::move($1); } + | stmt_waittill { $$.as_waittill = std::move($1); } + | stmt_waittillmatch { $$.as_waittillmatch = std::move($1); } + | stmt_waittillframeend { $$.as_waittillframeend = std::move($1); } + | stmt_waitframe { $$.as_waitframe = std::move($1); } + | stmt_if { $$.as_if = std::move($1); } + | stmt_ifelse { $$.as_ifelse = std::move($1); } + | stmt_while { $$.as_while = std::move($1); } + | stmt_for { $$.as_for = std::move($1); } + | stmt_foreach { $$.as_foreach = std::move($1); } + | stmt_switch { $$.as_switch = std::move($1); } + | stmt_case { $$.as_case = std::move($1); } + | stmt_default { $$.as_default = std::move($1); } + | stmt_break { $$.as_break = std::move($1); } + | stmt_continue { $$.as_continue = std::move($1); } + | stmt_return { $$.as_return = std::move($1); } + ; + +stmt_block + : LBRACE stmt_list RBRACE { $$ = std::move($2); } + | LBRACE RBRACE { $$ = std::make_unique(@$); } + ; + +stmt_list + : stmt_list stmt + { $$ = std::move($1); $$->stmts.push_back(std::move($2)); } + | stmt + { $$ = std::make_unique(@$); $$->stmts.push_back(std::move($1)); } + ; + +stmt_call + : expr_call SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + | expr_call_thread SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + ; + +stmt_assign + : expr_assign SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + ; + +stmt_endon + : object ENDON LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4)); } + ; + +stmt_notify + : object NOTIFY LPAREN expr COMMA expr_arguments RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | object NOTIFY LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::make_unique(@$)); } + ; + +stmt_wait + : WAIT expr SEMICOLON + { $$ = std::make_unique(@$, std::move($2)); } + ; + +stmt_waittill + : object WAITTILL LPAREN expr COMMA expr_arguments RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | object WAITTILL LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::make_unique(@$)); } + ; + +stmt_waittillmatch + : object WAITTILLMATCH LPAREN expr COMMA expr_arguments RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::make_unique(@$)); } + ; + +stmt_waittillframeend + : WAITTILLFRAMEEND SEMICOLON + { $$ = std::make_unique(@$); } + ; + +stmt_waitframe + : WAITFRAME SEMICOLON + { $$ = std::make_unique(@$); } + | WAITFRAME LPAREN RPAREN SEMICOLON + { $$ = std::make_unique(@$); } + ; + +stmt_if + : IF LPAREN expr RPAREN stmt %prec THEN + { $$ = std::make_unique(@$, std::move($3), std::move($5)); } + ; + +stmt_ifelse + : IF LPAREN expr RPAREN stmt ELSE stmt + { $$ = std::make_unique(@$, std::move($3), std::move($5), std::move($7)); } + ; + +stmt_while + : WHILE LPAREN expr RPAREN stmt + { $$ = std::make_unique(@$, std::move($3), std::move($5)); } + ; + +stmt_for + : FOR LPAREN for_stmt SEMICOLON for_expr SEMICOLON for_stmt RPAREN stmt + { $$ = std::make_unique(@$, std::move($3), std::move($5), std::move($7), std::move($9)); } + ; + +stmt_foreach + : FOREACH LPAREN name IN expr RPAREN stmt + { $$ = std::make_unique(@$, expr_ptr(std::move($3)), std::move($5), std::move($7)); } + | FOREACH LPAREN name COMMA name IN expr RPAREN stmt + { $$ = std::make_unique(@$, expr_ptr(std::move($3)), expr_ptr(std::move($5)), std::move($7), std::move($9)); } + ; + +stmt_switch + : SWITCH LPAREN expr RPAREN stmt_block + { $$ = std::make_unique(@$, std::move($3), std::move($5)); } + ; + +stmt_case + : CASE integer COLON + { $$ = std::make_unique(@$, expr_ptr(std::move($2)), std::make_unique(@$)); } + | CASE string COLON + { $$ = std::make_unique(@$, expr_ptr(std::move($2)), std::make_unique(@$)); } + ; + +stmt_default + : DEFAULT COLON + { $$ = std::make_unique(@$, std::make_unique(@$)); } + ; + +stmt_break + : BREAK SEMICOLON + { $$ = std::make_unique(@$); } + ; + +stmt_continue + : CONTINUE SEMICOLON + { $$ = std::make_unique(@$); } + ; + +stmt_return + : RETURN expr SEMICOLON + { $$ = std::make_unique(@$, std::move($2)); } + | RETURN SEMICOLON + { $$ = std::make_unique(@$, std::make_unique(@$)); } + ; + +for_stmt + : expr_assign { $$.as_list = std::make_unique(@$); $$.as_list->stmts.push_back(stmt_ptr(std::make_unique(@$, std::move($1)))); } + | { $$.as_node = std::make_unique(@$); } + ; + +for_expr + : expr { $$ = std::move($1); } + | { $$.as_node = std::make_unique(@$); } + ; + +expr + : expr_compare { $$ = std::move($1); } + | expr_ternary { $$ = std::move($1); } + | expr_binary { $$ = std::move($1); } + | expr_primitive { $$ = std::move($1); } + ; + +expr_assign + : INCREMENT object %prec PREINC { $$ = std::make_unique(@$, std::move($2)); } + | DECREMENT object %prec PREDEC { $$ = std::make_unique(@$, std::move($2)); } + | object INCREMENT %prec POSTINC { $$ = std::make_unique(@$, std::move($1)); } + | object DECREMENT %prec POSTDEC { $$ = std::make_unique(@$, std::move($1)); } + | object ASSIGN expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_BITWISE_OR expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_BITWISE_AND expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_BITWISE_EXOR expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_LSHIFT expr { $$ = std::make_unique(@$, std::move($1),std::move( $3)); } + | object ASSIGN_RSHIFT expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_ADD expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_SUB expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_MULT expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_DIV expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + | object ASSIGN_MOD expr { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_compare + : expr OR expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr AND expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr EQUALITY expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr INEQUALITY expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr LESS_EQUAL expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr GREATER_EQUAL expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr LESS expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr GREATER expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_ternary + : expr QMARK expr COLON expr %prec TERN { $$.as_node = std::make_unique(@$, std::move($1), std::move($3), std::move($5)); } + ; + +expr_binary + : expr BITWISE_OR expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr BITWISE_AND expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr BITWISE_EXOR expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr LSHIFT expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr RSHIFT expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr ADD expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr SUB expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr MULT expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr DIV expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr MOD expr { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_primitive + : LPAREN expr RPAREN { $$ = std::move($2); } + | COMPLEMENT expr { $$.as_node = std::make_unique(@$, std::move($2)); } + | NOT expr { $$.as_node = std::make_unique(@$, std::move($2)); } + | expr_call { $$.as_node = std::move($1); } + | expr_call_thread { $$.as_node = std::move($1); } + | expr_call_childthread { $$.as_node = std::move($1); } + | expr_function { $$.as_node = std::move($1); } + | expr_add_array { $$.as_node = std::move($1); } + | expr_array { $$.as_node = std::move($1); } + | expr_field { $$.as_node = std::move($1); } + | expr_size { $$.as_node = std::move($1); } + | thisthread { $$.as_node = std::move($1); } + | empty_array { $$.as_node = std::move($1); } + | undefined { $$.as_node = std::move($1); } + | game { $$.as_node = std::move($1); } + | self { $$.as_node = std::move($1); } + | anim { $$.as_node = std::move($1); } + | level { $$.as_node = std::move($1); } + | animation { $$.as_node = std::move($1); } + | animtree { $$.as_node = std::move($1); } + | name { $$.as_node = std::move($1); } + | istring { $$.as_node = std::move($1); } + | string { $$.as_node = std::move($1); } + | color { $$.as_node = std::move($1); } + | vector { $$.as_node = std::move($1); } + | float { $$.as_node = std::move($1); } + | integer { $$.as_node = std::move($1); } + | false { $$.as_node = std::move($1); } + | true { $$.as_node = std::move($1); } + ; + +expr_call + : expr_call_function { $$ = std::make_unique(@$, false, false, std::make_unique(@$), std::move($1)); } + | expr_call_pointer { $$ = std::make_unique(@$, false, false, std::make_unique(@$), std::move($1)); } + | object expr_call_function { $$ = std::make_unique(@$, false, false, std::move($1), std::move($2)); } + | object expr_call_pointer { $$ = std::make_unique(@$, false, false, std::move($1), std::move($2)); } + ; + +expr_call_thread + : THREAD expr_call_function { $$ = std::make_unique(@$, true, false, std::make_unique(@$), std::move($2)); } + | THREAD expr_call_pointer { $$ = std::make_unique(@$, true, false, std::make_unique(@$), std::move($2)); } + | object THREAD expr_call_function { $$ = std::make_unique(@$, true, false, std::move($1), std::move($3)); } + | object THREAD expr_call_pointer { $$ = std::make_unique(@$, true, false, std::move($1), std::move($3)); } + ; + +expr_call_childthread + : CHILDTHREAD expr_call_function { $$ = std::make_unique(@$, false, true, std::make_unique(@$), std::move($2)); } + | CHILDTHREAD expr_call_pointer { $$ = std::make_unique(@$, false, true, std::make_unique(@$), std::move($2)); } + | object CHILDTHREAD expr_call_function { $$ = std::make_unique(@$, false, true, std::move($1), std::move($3)); } + | object CHILDTHREAD expr_call_pointer { $$ = std::make_unique(@$, false, true, std::move($1), std::move($3)); } + ; + +expr_call_function + : name LPAREN expr_arguments RPAREN + {$$.as_func = std::make_unique(@$, std::make_unique(), std::move($1), std::move($3)); } + | file DOUBLECOLON name LPAREN expr_arguments RPAREN + { $$.as_func = std::make_unique(@$, std::move($1), std::move($3), std::move($5)); } + ; + +expr_call_pointer + : LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, false, std::move($3), std::move($7)); } + | CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, true, std::move($4), std::move($8)); } + ; + +expr_arguments + : expr_arguments_filled { $$ = std::move($1); } + | expr_arguments_empty { $$ = std::move($1); } + ; + +expr_arguments_filled + : expr_arguments COMMA expr + { $$ = std::move($1); $$->list.push_back(std::move($3)); } + | expr %prec ADD_ARRAY + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + ; + +expr_arguments_empty + : + { $$ = std::make_unique(@$); } + ; + +expr_function + : DOUBLECOLON name + { $$ = std::make_unique(@$, std::make_unique(@$), std::move($2)); } + | file DOUBLECOLON name + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_add_array + : LBRACKET expr_arguments_filled RBRACKET + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_array + : object LBRACKET expr RBRACKET + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_field + : object DOT name + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_size + : object DOT SIZE + { $$ = std::make_unique(@$, std::move($1)); } + ; + +object + : expr_call { $$ = std::move($1); } + | expr_array { $$ = std::move($1); } + | expr_field { $$ = std::move($1); } + | game { $$ = std::move($1); } + | self { $$ = std::move($1); } + | anim { $$ = std::move($1); } + | level { $$ = std::move($1); } + | name { $$ = std::move($1); } + ; + +float + : SUB FLOAT %prec NEG { $$ = std::make_unique(@$, "-" + $2); }; + | FLOAT { $$ = std::make_unique(@$, $1); }; + ; + +integer + : SUB INT_DEC %prec NEG { $$ = std::make_unique(@$, "-" + $2); }; + | INT_DEC { $$ = std::make_unique(@$, $1); }; + | INT_OCT { $$ = std::make_unique(@$, $1); }; + | INT_BIN { $$ = std::make_unique(@$, $1); }; + | INT_HEX { $$ = std::make_unique(@$, $1); }; + ; + +thisthread : THISTHREAD { $$ = std::make_unique(@$); }; +empty_array : LBRACKET RBRACKET { $$ = std::make_unique(@$); }; +undefined : UNDEFINED { $$ = std::make_unique(@$); }; +game : GAME { $$ = std::make_unique(@$); }; +self : SELF { $$ = std::make_unique(@$); }; +anim : ANIM { $$ = std::make_unique(@$); }; +level : LEVEL { $$ = std::make_unique(@$); }; +animation : MOD NAME %prec ANIMREF { $$ = std::make_unique(@$, $2); }; +animtree : ANIMTREE { $$ = std::make_unique(@$); }; +name : NAME { $$ = std::make_unique(@$, $1); }; +file : FILE { $$ = std::make_unique(@$, $1); }; +istring : ISTRING { $$ = std::make_unique(@$, $1); }; +string : STRING { $$ = std::make_unique(@$, $1); }; +color : COLOR { $$ = std::make_unique(@$, $1); }; +vector : LPAREN expr COMMA expr COMMA expr RPAREN { $$ = std::make_unique(@$, std::move($2), std::move($4), std::move($6)); }; +false : FALSE { $$ = std::make_unique(@$); }; +true : TRUE { $$ = std::make_unique(@$); }; + +%% + +void xsk::gsc::s4::parser::error(const xsk::gsc::location& loc, const std::string& msg) +{ + throw xsk::gsc::comp_error(loc, msg); +} diff --git a/premake5.lua b/premake5.lua index 4e736b1b..0321afa1 100644 --- a/premake5.lua +++ b/premake5.lua @@ -55,6 +55,7 @@ project "xsk-gsc-tool" dependson "xsk-gsc-iw8" dependson "xsk-gsc-s1" dependson "xsk-gsc-s2" + dependson "xsk-gsc-s4" dependson "xsk-gsc-h1" dependson "xsk-gsc-h2" @@ -75,6 +76,7 @@ project "xsk-gsc-tool" "xsk-gsc-iw8", "xsk-gsc-s1", "xsk-gsc-s2", + "xsk-gsc-s4", "xsk-gsc-h1", "xsk-gsc-h2" } @@ -214,6 +216,24 @@ project "xsk-gsc-s2" "./src" } +project "xsk-gsc-s4" + kind "StaticLib" + language "C++" + + pchheader "stdafx.hpp" + pchsource "src/s4/stdafx.cpp" + + files { + "./src/s4/**.h", + "./src/s4/**.hpp", + "./src/s4/**.cpp" + } + + includedirs { + "./src/s4", + "./src" + } + project "xsk-gsc-h1" kind "StaticLib" language "C++" diff --git a/src/s4/stdafx.cpp b/src/s4/stdafx.cpp new file mode 100644 index 00000000..0f0f08c2 --- /dev/null +++ b/src/s4/stdafx.cpp @@ -0,0 +1,6 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#include "stdafx.hpp" diff --git a/src/s4/stdafx.hpp b/src/s4/stdafx.hpp new file mode 100644 index 00000000..bb466e1d --- /dev/null +++ b/src/s4/stdafx.hpp @@ -0,0 +1,38 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#pragma once + +// Warnings +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4267) +#pragma warning(disable:4005) +#pragma warning(disable:4065) +#define _CRT_SECURE_NO_WARNINGS +#endif + +// C/C++ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Ext +using namespace std::literals; + +#include "xsk/s4.hpp" diff --git a/src/s4/xsk/assembler.cpp b/src/s4/xsk/assembler.cpp new file mode 100644 index 00000000..a2ad0eb1 --- /dev/null +++ b/src/s4/xsk/assembler.cpp @@ -0,0 +1,682 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#include "stdafx.hpp" +#include "s4.hpp" + +namespace xsk::gsc::s4 +{ + +auto assembler::output_script() -> std::vector +{ + std::vector script; + + if(script_ == nullptr) return script; + + script.resize(script_->pos()); + memcpy(script.data(), script_->buffer().data(), script.size()); + + return script; +} + +auto assembler::output_stack() -> std::vector +{ + std::vector stack; + + if(stack_ == nullptr) return stack; + + stack.resize(stack_->pos()); + memcpy(stack.data(), stack_->buffer().data(), stack.size()); + + return stack; +} + +void assembler::assemble(const std::string& file, std::vector& data) +{ + std::vector assembly = utils::string::clean_buffer_lines(data); + std::vector functions; + gsc::function_ptr func = nullptr; + std::uint32_t index = 1; + std::uint16_t switchnum = 0; + + for (auto& line : assembly) + { + if (line == "" || line.substr(0, 2) == "//") + { + continue; + } + else if (line.substr(0, 4) == "sub_") + { + func = std::make_unique(); + func->index = index; + func->name = line.substr(4); + } + else if (line.substr(0, 4) == "end_") + { + if (func != nullptr) + { + func->size = index - func->index; + functions.push_back(std::move(func)); + } + } + else if (line.substr(0, 4) == "loc_") + { + func->labels[index] = line; + } + else + { + auto data = utils::string::parse_code(line); + + if (switchnum) + { + if (data[0] == "case" || data[0] == "default") + { + for (auto& entry : data) + { + func->instructions.back()->data.push_back(entry); + } + switchnum--; + continue; + } + + throw gsc::asm_error("invalid instruction inside endswitch \""s + line + "\"!"); + } + else + { + auto inst = std::make_unique(); + inst->index = index; + inst->opcode = static_cast(resolver::opcode_id(data[0])); + inst->size = opcode_size(inst->opcode); + data.erase(data.begin()); + inst->data = std::move(data); + + if (opcode(inst->opcode) == opcode::OP_endswitch) + { + switchnum = static_cast(std::stoi(inst->data[0])); + inst->size += 7 * switchnum; + } + + index += inst->size; + func->instructions.push_back(std::move(inst)); + } + } + } + + this->assemble(file, functions); +} + +void assembler::assemble(const std::string& file, std::vector& functions) +{ + script_ = std::make_unique(0x100000); + stack_ = std::make_unique(0x100000); + filename_ = file; + functions_ = std::move(functions); + + script_->write(static_cast(opcode::OP_End)); + + for (const auto& func : functions_) + { + this->assemble_function(func); + } +} + +void assembler::assemble_function(const gsc::function_ptr& func) +{ + labels_ = func->labels; + + stack_->write(func->size); + + func->id = func->name.substr(0, 3) == "_ID" ? std::stoi(func->name.substr(3)) : resolver::token_id(func->name); + stack_->write(func->id); + + if (func->id == 0) + { + stack_->write_c_string(func->name); + } + + for (const auto& inst : func->instructions) + { + this->assemble_instruction(inst); + } +} + +void assembler::assemble_instruction(const gsc::instruction_ptr& inst) +{ + switch (opcode(inst->opcode)) + { + case opcode::OP_CastFieldObject: + case opcode::OP_plus: + case opcode::OP_GetGameRef: + case opcode::OP_GetThisthread: + case opcode::OP_greater: + case opcode::OP_shift_right: + case opcode::OP_dec: + case opcode::OP_bit_or: + case opcode::OP_equality: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_notify: + case opcode::OP_PreScriptCall: + case opcode::OP_GetUndefined: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_GetLevel: + case opcode::OP_size: + case opcode::OP_AddArray: + case opcode::OP_endon: + case opcode::OP_shift_left: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_Return: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_GetSelfObject: + case opcode::OP_GetGame: + case opcode::OP_EvalArray: + case opcode::OP_GetSelf: + case opcode::OP_End: + case opcode::OP_less_equal: + case opcode::OP_EvalLocalVariableCached0: + case opcode::OP_EvalLocalVariableCached1: + case opcode::OP_EvalLocalVariableCached2: + case opcode::OP_EvalLocalVariableCached3: + case opcode::OP_EvalLocalVariableCached4: + case opcode::OP_EvalLocalVariableCached5: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_checkclearparams: + case opcode::OP_waittillmatch2: + case opcode::OP_minus: + case opcode::OP_greater_equal: + case opcode::OP_vector: + case opcode::OP_ClearArray: + case opcode::OP_DecTop: + case opcode::OP_CastBool: + case opcode::OP_EvalArrayRef: + case opcode::OP_GetZero: + case opcode::OP_wait: + case opcode::OP_waittill: + case opcode::OP_GetAnimObject: + case opcode::OP_mod: + case opcode::OP_clearparams: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_EmptyArray: + case opcode::OP_ClearVariableField: + case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_BoolComplement: + case opcode::OP_less: + case opcode::OP_BoolNot: + case opcode::OP_waittillFrameEnd: + case opcode::OP_waitframe: + case opcode::OP_GetLevelObject: + case opcode::OP_inc: + case opcode::OP_GetAnim: + case opcode::OP_SetVariableField: + case opcode::OP_divide: + case opcode::OP_multiply: + case opcode::OP_EvalLocalVariableRefCached0: + case opcode::OP_bit_and: + case opcode::OP_voidCodepos: + case opcode::OP_inequality: + case opcode::OP_bit_ex_or: +/* + case opcode::OP_NOP: + case opcode::OP_abort: + case opcode::OP_object: + case opcode::OP_thread_object: + case opcode::OP_EvalLocalVariable: + case opcode::OP_EvalLocalVariableRef: + case opcode::OP_breakpoint: + case opcode::OP_assignmentBreakpoint: + case opcode::OP_manualAndAssignmentBreakpoint: +*/ + case opcode::OP_BoolNotAfterAnd: + case opcode::OP_IsDefined: + case opcode::OP_IsTrue: + script_->write(static_cast(inst->opcode)); + break; + case opcode::OP_GetByte: + script_->write(static_cast(inst->opcode)); + script_->write(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetNegByte: + script_->write(static_cast(inst->opcode)); + script_->write(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetUnsignedShort: + script_->write(static_cast(inst->opcode)); + script_->write(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetNegUnsignedShort: + script_->write(static_cast(inst->opcode)); + script_->write(static_cast(std::stoi(inst->data[0]))); + case opcode::OP_GetInteger: + script_->write(static_cast(inst->opcode)); + script_->write(std::stoi(inst->data[0])); + break; + case opcode::OP_GetFloat: + script_->write(static_cast(inst->opcode)); + script_->write(std::stof(inst->data[0])); + break; + case opcode::OP_GetVector: + script_->write(static_cast(inst->opcode)); + script_->write(std::stof(inst->data[0])); + script_->write(std::stof(inst->data[1])); + script_->write(std::stof(inst->data[2])); + break; + case opcode::OP_GetString: + case opcode::OP_GetIString: + script_->write(static_cast(inst->opcode)); + script_->write(0); + stack_->write_c_string(utils::string::to_code(inst->data[0])); + break; + case opcode::OP_GetAnimation: + script_->write(static_cast(inst->opcode)); + script_->write(0); + script_->write(0); + stack_->write_c_string(utils::string::unquote(inst->data[0])); + stack_->write_c_string(utils::string::unquote(inst->data[1])); + break; + case opcode::OP_GetAnimTree: + script_->write(static_cast(inst->opcode)); + script_->write(0); + stack_->write_c_string(utils::string::unquote(inst->data[0])); + break; + case opcode::OP_waittillmatch: + script_->write(static_cast(inst->opcode)); + script_->write(0); + break; + case opcode::OP_SetNewLocalVariableFieldCached0: + case opcode::OP_EvalNewLocalArrayRefCached0: + case opcode::OP_SafeCreateVariableFieldCached: + case opcode::OP_ClearLocalVariableFieldCached: + case opcode::OP_SetLocalVariableFieldCached: + case opcode::OP_RemoveLocalVariables: + case opcode::OP_EvalLocalVariableRefCached: + case opcode::OP_EvalLocalArrayRefCached: + case opcode::OP_SafeSetVariableFieldCached: + case opcode::OP_EvalLocalVariableCached: + case opcode::OP_SafeSetWaittillVariableFieldCached: + case opcode::OP_CreateLocalVariable: + case opcode::OP_EvalLocalVariableObjectCached: + case opcode::OP_EvalLocalArrayCached: + script_->write(static_cast(inst->opcode)); + script_->write(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_EvalSelfFieldVariable: + case opcode::OP_SetLevelFieldVariableField: + case opcode::OP_ClearFieldVariable: + case opcode::OP_EvalFieldVariable: + case opcode::OP_EvalFieldVariableRef: + case opcode::OP_EvalLevelFieldVariable: + case opcode::OP_SetAnimFieldVariableField: + case opcode::OP_SetSelfFieldVariableField: + case opcode::OP_EvalAnimFieldVariableRef: + case opcode::OP_EvalLevelFieldVariableRef: + case opcode::OP_EvalAnimFieldVariable: + case opcode::OP_EvalSelfFieldVariableRef: + this->assemble_field_variable(inst); + break; + case opcode::OP_CallBuiltinPointer: + case opcode::OP_CallBuiltinMethodPointer: + case opcode::OP_ScriptThreadCallPointer: + case opcode::OP_ScriptChildThreadCallPointer: + case opcode::OP_ScriptMethodThreadCallPointer: + case opcode::OP_ScriptMethodChildThreadCallPointer: + script_->write(static_cast(inst->opcode)); + script_->write(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalMethodCall: + this->assemble_local_call(inst, false); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + this->assemble_local_call(inst, true); + break; + case opcode::OP_GetFarFunction: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarMethodCall: + this->assemble_far_call(inst, false); + break; + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_ScriptFarMethodChildThreadCall: + this->assemble_far_call(inst, true); + break; + case opcode::OP_CallBuiltin: + this->assemble_builtin_call(inst, false, true); + break; + case opcode::OP_CallBuiltinMethod: + this->assemble_builtin_call(inst, true, true); + break; + case opcode::OP_GetBuiltinFunction: + case opcode::OP_CallBuiltin0: + case opcode::OP_CallBuiltin1: + case opcode::OP_CallBuiltin2: + case opcode::OP_CallBuiltin3: + case opcode::OP_CallBuiltin4: + case opcode::OP_CallBuiltin5: + this->assemble_builtin_call(inst, false, false); + break; + case opcode::OP_GetBuiltinMethod: + case opcode::OP_CallBuiltinMethod0: + case opcode::OP_CallBuiltinMethod1: + case opcode::OP_CallBuiltinMethod2: + case opcode::OP_CallBuiltinMethod3: + case opcode::OP_CallBuiltinMethod4: + case opcode::OP_CallBuiltinMethod5: + this->assemble_builtin_call(inst, true, false); + break; + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + this->assemble_jump(inst, true, false); + break; + case opcode::OP_jumpback: + this->assemble_jump(inst, false, true); + break; + case opcode::OP_jump: + this->assemble_jump(inst, false, false); + break; + case opcode::OP_switch: + this->assemble_switch(inst); + break; + case opcode::OP_endswitch: + this->assemble_end_switch(inst); + break; +/* + case opcode::OP_prof_begin: + script_->write(0); // TODO: skipped data + script_->write(0); + break; + case opcode::OP_prof_end: + script_->write(0); // TODO: skipped data + break; + case opcode::OP_EvalNewLocalArrayRefCached0_Precompiled: + case opcode::OP_SetNewLocalVariableFieldCached0_Precompiled: + case opcode::OP_CreateLocalVariable_Precompiled: + case opcode::OP_SafeCreateVariableFieldCached_Precompiled: + script_->write(static_cast(inst->opcode)); + script_->write(static_cast(std::stoi(inst->data[0]))); + break; +*/ + case opcode::OP_FormalParams: +// case opcode::OP_FormalParams_Precompiled: + this->assemble_formal_params(inst); + break; +/* + case opcode::OP_NativeGetLocalFunction: + case opcode::OP_NativeLocalFunctionCall: + case opcode::OP_NativeLocalFunctionCall2: + case opcode::OP_NativeLocalMethodCall: + this->assemble_local_call(inst, false); + break; + case opcode::OP_NativeGetFarFunction: + case opcode::OP_NativeFarFunctionCall: + case opcode::OP_NativeFarFunctionCall2: + case opcode::OP_NativeFarMethodCall: + this->assemble_far_call(inst, false); + break; + case opcode::OP_NativeLocalFunctionThreadCall: + case opcode::OP_NativeLocalMethodThreadCall: + case opcode::OP_NativeLocalFunctionChildThreadCall: + case opcode::OP_NativeLocalMethodChildThreadCall: + this->assemble_local_call(inst, true); + break; + case opcode::OP_NativeFarFunctionThreadCall: + case opcode::OP_NativeFarMethodThreadCall: + case opcode::OP_NativeFarFunctionChildThreadCall: + case opcode::OP_NativeFarMethodChildThreadCall: + this->assemble_far_call(inst, true); + break; +*/ + default: + throw gsc::asm_error(utils::string::va("Unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index)); + } +} + +void assembler::assemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num) +{ + script_->write(static_cast(inst->opcode)); + + std::uint16_t id = 0; + + if (arg_num) + { + script_->write(static_cast(std::stoi(inst->data[0]))); + + if (method) + id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::method_id(inst->data[1]); + else + id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::function_id(inst->data[1]); + } + else + { + if (method) + id = inst->data[0].substr(0, 3) == "_ID" ? std::stoi(inst->data[0].substr(3)) : resolver::method_id(inst->data[0]); + else + id = inst->data[0].substr(0, 3) == "_ID" ? std::stoi(inst->data[0].substr(3)) : resolver::function_id(inst->data[0]); + } + + script_->write(id); +} + +void assembler::assemble_local_call(const gsc::instruction_ptr& inst, bool thread) +{ + script_->write(static_cast(inst->opcode)); + + std::int32_t addr = this->resolve_function(inst->data[0]); + + std::int32_t offset = addr - inst->index - 1; + + this->assemble_offset(offset); + + if (thread) + { + script_->write(static_cast(std::stoi(inst->data[1]))); + } +} + +void assembler::assemble_far_call(const gsc::instruction_ptr& inst, bool thread) +{ + script_->write(static_cast(inst->opcode)); + script_->write(0); + script_->write(0); + + std::uint32_t file_id = 0; + std::uint32_t func_id = 0; + + if (thread) + { + script_->write(static_cast(std::stoi(inst->data[0]))); + + file_id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::file_id(inst->data[1]); + func_id = inst->data[2].substr(0, 3) == "_ID" ? std::stoi(inst->data[2].substr(3)) : resolver::token_id(inst->data[2]); + } + else + { + file_id = inst->data[0].substr(0, 3) == "_ID" ? std::stoi(inst->data[0].substr(3)) : resolver::file_id(inst->data[0]); + func_id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::token_id(inst->data[1]); + } + + stack_->write(file_id); + if (file_id == 0) stack_->write_c_string(thread ? inst->data[1] : inst->data[0]); + stack_->write(func_id); + if (func_id == 0) stack_->write_c_string(thread ? inst->data[2] : inst->data[1]); +} + +void assembler::assemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back) +{ + script_->write(static_cast(inst->opcode)); + + std::int32_t addr = this->resolve_label(inst->data[0]); + + if (expr) + { + script_->write(addr - inst->index - 3); + } + else if (back) + { + script_->write((inst->index + 3) - addr); + } + else + { + script_->write(addr - inst->index - 5); + } +} + +void assembler::assemble_field_variable(const gsc::instruction_ptr& inst) +{ + script_->write(static_cast(inst->opcode)); + + std::uint32_t field_id = 0; + + if (inst->data[0].substr(0, 3) == "_ID") + { + field_id = std::stoi(inst->data[0].substr(3)); + } + else + { + field_id = resolver::token_id(inst->data[0]); + + if (field_id == 0) + { + field_id = 0xFFFF; + } + } + + script_->write(field_id); + + if (field_id > 0x1C000) + { + stack_->write(0); + stack_->write_c_string(inst->data[0]); + } +} + +void assembler::assemble_formal_params(const gsc::instruction_ptr& inst) +{ + script_->write(static_cast(inst->opcode)); + + auto size = std::stoi(inst->data[0]); + + script_->write(static_cast(size)); + + for(auto i = 1; i <= size; i++) + { + script_->write(static_cast(std::stoi(inst->data[i]))); + } +} + +void assembler::assemble_switch(const gsc::instruction_ptr& inst) +{ + script_->write(static_cast(inst->opcode)); + + std::int32_t addr = this->resolve_label(inst->data[0]); + + script_->write(addr - inst->index - 4); +} + +void assembler::assemble_end_switch(const gsc::instruction_ptr& inst) +{ + script_->write(static_cast(inst->opcode)); + + std::uint16_t casenum = 0; + + if (utils::string::is_number(inst->data[0])) + { + casenum = std::stoi(inst->data[0]); + } + else + { + throw gsc::asm_error("invalid endswitch number!"); + } + + script_->write(casenum); + + std::uint32_t internal_index = inst->index + 3; + + for (std::uint16_t i = 0; i < casenum; i++) + { + if (inst->data[1 + (3 * i)] == "case") + { + if (utils::string::is_number(inst->data[1 + (3 * i) + 1])) + { + script_->write((std::stoi(inst->data[1 + (3 * i) + 1]) & 0xFFFFFF) + 0x800000); + } + else + { + script_->write(i + 1); + stack_->write_c_string(utils::string::unquote(inst->data[1 + (3 * i) + 1])); + } + + internal_index += 4; + + std::int32_t addr = this->resolve_label(inst->data[1 + (3 * i) + 2]); + + this->assemble_offset(addr - internal_index); + + internal_index += 3; + } + else if (inst->data[1 + (3 * i)] == "default") + { + script_->write(0); + stack_->write_c_string("\x01"); + + internal_index += 4; + std::int32_t addr = this->resolve_label(inst->data[1 + (3 * i) + 1]); + + this->assemble_offset(addr - internal_index); + + internal_index += 3; + } + } +} + +void assembler::assemble_offset(std::int32_t offset) +{ + std::array bytes = {}; + + offset = (offset << 8) >> 8; + + *reinterpret_cast(bytes.data()) = offset; + + script_->write(bytes[0]); + script_->write(bytes[1]); + script_->write(bytes[2]); +} + +auto assembler::resolve_function(const std::string& name) -> std::uint32_t +{ + auto temp = name.substr(0, 4) == "sub_" ? name.substr(4) : name; + + for (const auto& func : functions_) + { + if (func->name == temp) + { + return func->index; + } + } + + throw gsc::asm_error("Couldn't resolve local function address of '" + temp + "'!"); +} + +auto assembler::resolve_label(const std::string& name) -> std::uint32_t +{ + for (auto& func : labels_) + { + if (func.second == name) + { + return func.first; + } + } + + throw gsc::asm_error("Couldn't resolve label address of '" + name + "'!"); +} + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/assembler.hpp b/src/s4/xsk/assembler.hpp new file mode 100644 index 00000000..72db0dbf --- /dev/null +++ b/src/s4/xsk/assembler.hpp @@ -0,0 +1,41 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#pragma once + +namespace xsk::gsc::s4 +{ + +class assembler : public gsc::assembler +{ + std::string filename_; + utils::byte_buffer_ptr script_; + utils::byte_buffer_ptr stack_; + std::vector functions_; + std::unordered_map labels_; + +public: + auto output_script() -> std::vector; + auto output_stack() -> std::vector; + void assemble(const std::string& file, std::vector& data); + void assemble(const std::string& file, std::vector& functions); + +private: + void assemble_function(const gsc::function_ptr& func); + void assemble_instruction(const gsc::instruction_ptr& inst); + void assemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num); + void assemble_local_call(const gsc::instruction_ptr& inst, bool thread); + void assemble_far_call(const gsc::instruction_ptr& inst, bool thread); + void assemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back); + void assemble_field_variable(const gsc::instruction_ptr& inst); + void assemble_formal_params(const gsc::instruction_ptr& inst); + void assemble_switch(const gsc::instruction_ptr& inst); + void assemble_end_switch(const gsc::instruction_ptr& inst); + void assemble_offset(std::int32_t offset); + auto resolve_function(const std::string& name) -> std::uint32_t; + auto resolve_label(const std::string& name) -> std::uint32_t; +}; + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/compiler.cpp b/src/s4/xsk/compiler.cpp new file mode 100644 index 00000000..13c22deb --- /dev/null +++ b/src/s4/xsk/compiler.cpp @@ -0,0 +1,2453 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#include "stdafx.hpp" +#include "s4.hpp" +#include "parser.hpp" +#include "lexer.hpp" + +namespace xsk::gsc::s4 +{ + +auto compiler::output() -> std::vector +{ + return std::move(assembly_); +} + +void compiler::compile(const std::string& file, std::vector& data) +{ + filename_ = file; + + auto result = parse_buffer(filename_, data); + + compile_program(result); +} + +void compiler::set_readf_callback(std::function(const std::string&)> func) +{ + callback_readf_ = func; +} + +auto compiler::parse_buffer(const std::string& file, std::vector& data) -> gsc::program_ptr +{ + yyscan_t scanner; + gsc::location loc; + gsc::program_ptr result(nullptr); + + loc.initialize(&file); + // Add the two NULL terminators, required by flex. + data.push_back(0); + data.push_back(0); + + if (s4_lex_init(&scanner)) + exit(1); + + YY_BUFFER_STATE yybuffer = s4__scan_buffer(reinterpret_cast(data.data()), data.size(), scanner); + + parser parser(scanner, loc, result); + + if(parser.parse() || result == nullptr) + { + throw gsc::comp_error(loc, "An unknown error ocurred while parsing gsc file."); + } + + s4__delete_buffer(yybuffer, scanner); + s4_lex_destroy(scanner); + + return result; +} + +auto compiler::parse_file(const std::string& file) -> gsc::program_ptr +{ + auto buffer = callback_readf_(file); + auto result = parse_buffer(file, buffer); + + return result; +} + +void compiler::compile_program(const gsc::program_ptr& program) +{ + assembly_.clear(); + includes_.clear(); + animtrees_.clear(); + constants_.clear(); + local_functions_.clear(); + index_ = 1; + + for(const auto& def : program->definitions) + { + if(def.as_node->type == gsc::node_t::thread) + { + local_functions_.push_back(def.as_thread->name->value); + } + } + + for(const auto& include : program->includes) + { + emit_include(include); + } + + for(const auto& def : program->definitions) + { + emit_define(def); + } + +#ifdef DEBUG_GSC_COMPILER + print_debug_info(); +#endif +} + +void compiler::emit_include(const gsc::include_ptr& include) +{ + const auto& path = include->file->value; + + for(const auto& inc : includes_) + { + if(inc.name == path) + { + throw gsc::comp_error(include->loc, "error duplicated include file '" + path + "'."); + } + } + + if(map_known_includes(path)) return; + + try + { + auto program = parse_file(path); + + std::vector funcs; + + for(const auto& def : program->definitions) + { + if(def.as_node->type == gsc::node_t::thread) + { + funcs.push_back(def.as_thread->name->value); + } + } + + if(funcs.size() == 0) + { + throw gsc::comp_error(include->loc, "error empty include file '" + path + "'."); + } + + includes_.push_back(include_t(path, funcs)); + } + catch(const std::exception& e) + { + throw gsc::comp_error(include->loc, "error parsing include file '" + path + "': " + e.what()); + } +} + +void compiler::emit_define(const gsc::define_ptr& define) +{ + switch(define.as_node->type) + { + case gsc::node_t::usingtree: emit_usingtree(define.as_usingtree); break; + case gsc::node_t::constant: emit_constant(define.as_constant); break; + case gsc::node_t::thread: emit_thread(define.as_thread); break; + default: break; + } +} + +void compiler::emit_usingtree(const gsc::usingtree_ptr& animtree) +{ + animtrees_.push_back({ animtree->animtree->value, false }); +} + +void compiler::emit_constant(const gsc::constant_ptr& constant) +{ + constants_.insert({ constant->name->value, std::move(constant->value) }); +} + +void compiler::emit_thread(const gsc::thread_ptr& thread) +{ + function_ = std::make_unique(); + function_->index = index_; + function_->name = thread->name->value; + + auto ctx = std::make_unique(); + stack_idx_ = 0; + label_idx_ = 0; + can_break_ = false; + can_continue_ = false; + local_stack_.clear(); + break_ctxs_.clear(); + continue_ctxs_.clear(); + + process_thread(ctx, thread); + + emit_parameters(ctx, thread->params); + emit_stmt_list(ctx, thread->block, true); + emit_opcode(ctx, opcode::OP_End); + + function_->size = index_ - function_->index; + assembly_.push_back(std::move(function_)); +} + +void compiler::emit_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params) +{ + std::uint32_t num = params->list.size(); + + if(num) + { + std::vector data; + + data.push_back(utils::string::va("%d", params->list.size())); + + for(const auto& param : params->list) + { + initialize_variable(ctx, param); + data.push_back(variable_create_index(ctx, param)); + } + + emit_opcode(ctx, opcode::OP_FormalParams, data); + function_->instructions.back()->size += num; + index_ += num; + } + else + { + emit_opcode(ctx, opcode::OP_checkclearparams); + } +} + +void compiler::emit_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt, bool last) +{ + switch(stmt.as_node->type) + { + case gsc::node_t::stmt_list: emit_stmt_list(ctx, stmt.as_list, last); break; + case gsc::node_t::stmt_call: emit_stmt_call(ctx, stmt.as_call); break; + case gsc::node_t::stmt_assign: emit_stmt_assign(ctx, stmt.as_assign); break; + case gsc::node_t::stmt_endon: emit_stmt_endon(ctx, stmt.as_endon); break; + case gsc::node_t::stmt_notify: emit_stmt_notify(ctx, stmt.as_notify); break; + case gsc::node_t::stmt_wait: emit_stmt_wait(ctx, stmt.as_wait); break; + case gsc::node_t::stmt_waittill: emit_stmt_waittill(ctx, stmt.as_waittill); break; + case gsc::node_t::stmt_waittillmatch: emit_stmt_waittillmatch(ctx, stmt.as_waittillmatch); break; + case gsc::node_t::stmt_waittillframeend: emit_stmt_waittillframeend(ctx, stmt.as_waittillframeend); break; + case gsc::node_t::stmt_waitframe: emit_stmt_waitframe(ctx, stmt.as_waitframe); break; + case gsc::node_t::stmt_if: emit_stmt_if(ctx, stmt.as_if, last); break; + case gsc::node_t::stmt_ifelse: emit_stmt_ifelse(ctx, stmt.as_ifelse, last); break; + case gsc::node_t::stmt_while: emit_stmt_while(ctx, stmt.as_while); break; + case gsc::node_t::stmt_for: emit_stmt_for(ctx, stmt.as_for); break; + case gsc::node_t::stmt_foreach: emit_stmt_foreach(ctx, stmt.as_foreach); break; + case gsc::node_t::stmt_switch: emit_stmt_switch(ctx, stmt.as_switch); break; + case gsc::node_t::stmt_case: emit_stmt_case(ctx, stmt.as_case); break; + case gsc::node_t::stmt_default: emit_stmt_default(ctx, stmt.as_default); break; + case gsc::node_t::stmt_break: emit_stmt_break(ctx, stmt.as_break); break; + case gsc::node_t::stmt_continue: emit_stmt_continue(ctx, stmt.as_continue); break; + case gsc::node_t::stmt_return: emit_stmt_return(ctx, stmt.as_return); break; + default: break; + } +} + +void compiler::emit_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt, bool last) +{ + for (const auto& entry : stmt->stmts) + { + bool last_ = (&entry == &stmt->stmts.back() && last) ? true : false; + emit_stmt(ctx, entry, last_); + } +} + +void compiler::emit_stmt_call(const gsc::context_ptr& ctx, const gsc::stmt_call_ptr& stmt) +{ + if(stmt->expr->func.as_node->type == gsc::node_t::expr_call_function) + { + const auto& name = stmt->expr->func.as_func->name->value; + + if(name == "assert" || name == "assertex" || name == "assertmsg") return; + } + + emit_expr_call(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_DecTop); +} + +void compiler::emit_stmt_assign(const gsc::context_ptr& ctx, const gsc::stmt_assign_ptr& stmt) +{ + emit_expr_assign(ctx, stmt->expr); +} + +void compiler::emit_stmt_endon(const gsc::context_ptr& ctx, const gsc::stmt_endon_ptr& stmt) +{ + emit_expr(ctx, stmt->expr); + emit_expr(ctx, stmt->obj); + emit_opcode(ctx, opcode::OP_endon); +} + +void compiler::emit_stmt_notify(const gsc::context_ptr& ctx, const gsc::stmt_notify_ptr& stmt) +{ + emit_opcode(ctx, opcode::OP_voidCodepos); + + std::reverse(stmt->args->list.begin(), stmt->args->list.end()); + + for(const auto& arg : stmt->args->list) + { + emit_expr(ctx, arg); + } + + emit_expr(ctx, stmt->expr); + emit_expr(ctx, stmt->obj); + emit_opcode(ctx, opcode::OP_notify); +} + +void compiler::emit_stmt_wait(const gsc::context_ptr& ctx, const gsc::stmt_wait_ptr& stmt) +{ + emit_expr(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_wait); +} + +void compiler::emit_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt) +{ + emit_expr(ctx, stmt->expr); + emit_expr(ctx, stmt->obj); + emit_opcode(ctx, opcode::OP_waittill); + + for(const auto& arg : stmt->args->list) + { + create_variable(ctx, arg.as_name); + emit_opcode(ctx, opcode::OP_SafeSetWaittillVariableFieldCached, variable_access_index(ctx, arg.as_name)); + } + + emit_opcode(ctx, opcode::OP_clearparams); +} + +void compiler::emit_stmt_waittillmatch(const gsc::context_ptr& ctx, const gsc::stmt_waittillmatch_ptr& stmt) +{ + emit_expr_arguments(ctx, stmt->args); + emit_expr(ctx, stmt->expr); + emit_expr(ctx, stmt->obj); + emit_opcode(ctx, opcode::OP_waittillmatch); + emit_opcode(ctx, opcode::OP_clearparams); +} + +void compiler::emit_stmt_waittillframeend(const gsc::context_ptr& ctx, const gsc::stmt_waittillframeend_ptr& stmt) +{ + emit_opcode(ctx, opcode::OP_waittillFrameEnd); +} + +void compiler::emit_stmt_waitframe(const gsc::context_ptr& ctx, const gsc::stmt_waitframe_ptr& stmt) +{ + emit_opcode(ctx, opcode::OP_waitframe); +} + +void compiler::emit_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt, bool last) +{ + auto end_loc = create_label(); + + if(stmt->expr.as_node->type == gsc::node_t::expr_not) + { + emit_expr(ctx, stmt->expr.as_not->rvalue); + emit_opcode(ctx, opcode::OP_JumpOnTrue, end_loc); + } + else + { + emit_expr(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_JumpOnFalse, end_loc); + } + + ctx->transfer(stmt->ctx); + stmt->ctx->is_last = last; + + emit_stmt(stmt->ctx, stmt->stmt, last); + + last ? emit_opcode(ctx, opcode::OP_End) : emit_remove_local_vars(stmt->ctx); + + insert_label(end_loc); +} + +void compiler::emit_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt, bool last) +{ + std::vector childs; + auto else_loc = create_label(); + auto end_loc = create_label(); + + if(stmt->expr.as_node->type == gsc::node_t::expr_not) + { + emit_expr(ctx, stmt->expr.as_not->rvalue); + emit_opcode(ctx, opcode::OP_JumpOnTrue, else_loc); + } + else + { + emit_expr(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_JumpOnFalse, else_loc); + } + + ctx->transfer(stmt->ctx_if); + stmt->ctx_if->is_last = last; + + emit_stmt(stmt->ctx_if, stmt->stmt_if, last); + + emit_remove_local_vars(stmt->ctx_if); + + if(stmt->ctx_if->abort == abort_t::abort_none) + childs.push_back(stmt->ctx_if.get()); + + last ? emit_opcode(ctx, opcode::OP_End) : emit_opcode(ctx, opcode::OP_jump, end_loc); + + insert_label(else_loc); + + ctx->transfer(stmt->ctx_else); + stmt->ctx_else->is_last = last; + + emit_stmt(stmt->ctx_else, stmt->stmt_else, last); + + last ? emit_opcode(ctx, opcode::OP_End) : emit_remove_local_vars(stmt->ctx_else); + + if(stmt->ctx_else->abort == abort_t::abort_none) + childs.push_back(stmt->ctx_else.get()); + + insert_label(end_loc); + + ctx->init_from_child(childs); +} + +void compiler::emit_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt) +{ + auto old_breaks = break_ctxs_; + auto old_continues = continue_ctxs_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_ctxs_.clear(); + continue_ctxs_.clear(); + can_break_ = true; + can_continue_ = true; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + ctx->transfer(stmt->ctx); + stmt->ctx->loc_break = break_loc; + stmt->ctx->loc_continue = continue_loc; + + emit_create_local_vars(stmt->ctx); + + ctx->local_vars_create_count = stmt->ctx->local_vars_create_count; + + for(auto i = 0u; i < ctx->local_vars_create_count; i++) + { + if(!ctx->local_vars.at(i).init) + ctx->local_vars.at(i).init = true; + } + + auto begin_loc = insert_label(); + + bool const_cond = is_constant_condition(stmt->expr); + + if(!const_cond) + { + emit_expr(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_JumpOnFalse, break_loc); + } + + emit_stmt(stmt->ctx, stmt->stmt, false); + + insert_label(continue_loc); + emit_opcode(ctx, opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if(const_cond) + ctx->init_from_child(break_ctxs_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_ctxs_ = old_breaks; + continue_ctxs_ = old_continues; +} + +void compiler::emit_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt) +{ + auto old_breaks = break_ctxs_; + auto old_continues = continue_ctxs_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_ctxs_.clear(); + continue_ctxs_.clear(); + can_break_ = false; + can_continue_ = false; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + emit_stmt(ctx, stmt->pre_expr, false); + + ctx->transfer(stmt->ctx); + stmt->ctx->loc_break = break_loc; + stmt->ctx->loc_continue = continue_loc; + + emit_create_local_vars(stmt->ctx); + + ctx->local_vars_create_count = stmt->ctx->local_vars_create_count; + + for(auto i = 0u; i < ctx->local_vars_create_count; i++) + { + if(!ctx->local_vars.at(i).init) + ctx->local_vars.at(i).init = true; + } + + ctx->transfer(stmt->ctx_post); + + auto begin_loc = insert_label(); + + bool const_cond = is_constant_condition(stmt->expr); + + if(!const_cond) + { + emit_expr(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_JumpOnFalse, break_loc); + } + + can_break_ = true; + can_continue_ = true; + + emit_stmt(stmt->ctx, stmt->stmt, false); + + if(stmt->ctx->abort == abort_t::abort_none) + continue_ctxs_.push_back(stmt->ctx.get()); + + can_break_ = false; + can_continue_ = false; + + insert_label(continue_loc); + + stmt->ctx_post->init_from_child(continue_ctxs_); + + emit_stmt(stmt->ctx_post, stmt->post_expr, false); + emit_opcode(ctx, opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if(const_cond) + ctx->init_from_child(break_ctxs_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_ctxs_ = old_breaks; + continue_ctxs_ = old_continues; +} + +void compiler::emit_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt) +{ + auto old_breaks = break_ctxs_; + auto old_continues = continue_ctxs_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_ctxs_.clear(); + continue_ctxs_.clear(); + can_break_ = false; + can_continue_ = false; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + emit_expr(ctx, stmt->array_expr); + emit_variable_ref(ctx, stmt->array, true); + emit_variable(ctx, stmt->array); + emit_opcode(ctx, opcode::OP_CallBuiltin1, "getfirstarraykey"); + emit_variable_ref(ctx, stmt->key_expr, true); + + ctx->transfer(stmt->ctx); + stmt->ctx->loc_break = break_loc; + stmt->ctx->loc_continue = continue_loc; + + emit_create_local_vars(stmt->ctx); + + ctx->local_vars_create_count = stmt->ctx->local_vars_create_count; + + for(auto i = 0u; i < ctx->local_vars_create_count; i++) + { + if(!ctx->local_vars.at(i).init) + ctx->local_vars.at(i).init = true; + } + + ctx->transfer(stmt->ctx_post); + + auto begin_loc = insert_label(); + + emit_variable(ctx, stmt->key_expr); + emit_opcode(ctx, opcode::OP_IsDefined); + emit_opcode(ctx, opcode::OP_JumpOnFalse, break_loc); + + can_break_ = true; + can_continue_ = true; + + emit_variable(stmt->ctx, stmt->key_expr); + emit_opcode(stmt->ctx, opcode::OP_EvalLocalArrayCached, variable_access_index(stmt->ctx, stmt->array.as_name)); + emit_variable_ref(stmt->ctx, stmt->value_expr, true); + emit_stmt(stmt->ctx, stmt->stmt, false); + + if(stmt->ctx->abort == abort_t::abort_none) + continue_ctxs_.push_back(stmt->ctx.get()); + + can_break_ = false; + can_continue_ = false; + + insert_label(continue_loc); + + stmt->ctx_post->init_from_child(continue_ctxs_); + + emit_variable(stmt->ctx_post, stmt->key_expr); + emit_variable(stmt->ctx_post, stmt->array); + emit_opcode(stmt->ctx_post, opcode::OP_CallBuiltin2, "getnextarraykey"); + emit_variable_ref(stmt->ctx_post, stmt->key_expr, true); + emit_opcode(ctx, opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + emit_clear_local_variable(ctx, stmt->array.as_name); + if(!stmt->use_key) emit_clear_local_variable(ctx, stmt->key_expr.as_name); + + can_break_ = old_break; + can_continue_ = old_continue; + break_ctxs_ = old_breaks; + continue_ctxs_ = old_continues; +} + +void compiler::emit_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt) +{ + auto old_breaks = break_ctxs_; + auto old_break = can_break_; + break_ctxs_.clear(); + can_break_ = false; + + auto jmptable_loc = create_label(); + auto break_loc = create_label(); + + emit_expr(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_switch, jmptable_loc); + + can_break_ = true; + + std::vector data; + data.push_back(utils::string::va("%d", stmt->stmt->stmts.size())); + + bool has_default = false; + gsc::context* default_ctx = nullptr; + + for(auto i = 0; i < stmt->stmt->stmts.size(); i++) + { + auto& entry = stmt->stmt->stmts[i]; + + if(entry.as_node->type == gsc::node_t::stmt_case) + { + if(has_default) + { + gsc::comp_error(stmt->loc, "default must be last case"); + } + + auto& case_ = entry.as_case; + if(case_->value.as_node->type == gsc::node_t::data_integer) + { + auto loc = insert_label(); + data.push_back("case"); + data.push_back(case_->value.as_integer->value); + data.push_back(loc); + } + else if(case_->value.as_node->type == gsc::node_t::data_string) + { + auto loc = insert_label(); + data.push_back("case"); + data.push_back(case_->value.as_string->value); + data.push_back(loc); + } + else + { + throw gsc::comp_error(stmt->loc, "case type must be int or string"); + } + + ctx->transfer(case_->ctx); + case_->ctx->loc_break = break_loc; + emit_stmt_list(case_->ctx, case_->stmt, false); + if(case_->stmt->stmts.size() > 0) + emit_remove_local_vars(case_->ctx); + } + else if(entry.as_node->type == gsc::node_t::stmt_default) + { + auto loc = insert_label(); + data.push_back("default"); + data.push_back(loc); + + has_default = true; + default_ctx = entry.as_default->ctx.get(); + + ctx->transfer(entry.as_default->ctx); + entry.as_default->ctx->loc_break = break_loc; + emit_stmt_list(entry.as_default->ctx, entry.as_default->stmt, false); + if(entry.as_default->stmt->stmts.size() > 0) + emit_remove_local_vars(entry.as_default->ctx); + } + else + { + throw gsc::comp_error(entry.as_node->loc, "missing case statement"); + } + } + + if(has_default) + { + if(default_ctx->abort == abort_t::abort_none) + { + break_ctxs_.push_back(default_ctx); + } + ctx->init_from_child(break_ctxs_); + } + + insert_label(jmptable_loc); + + emit_opcode(ctx, opcode::OP_endswitch, data); + + auto offset = 7 * stmt->stmt->stmts.size(); + function_->instructions.back()->size += offset; + index_ += offset; + + insert_label(break_loc); + + can_break_ = old_break; + break_ctxs_ = old_breaks; +} + +void compiler::emit_stmt_case(const gsc::context_ptr& ctx, const gsc::stmt_case_ptr& stmt) +{ + throw gsc::comp_error(stmt->loc, "illegal case statement"); +} + +void compiler::emit_stmt_default(const gsc::context_ptr& ctx, const gsc::stmt_default_ptr& stmt) +{ + throw gsc::comp_error(stmt->loc, "illegal default statement"); +} + +void compiler::emit_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt) +{ + if(can_break_ && ctx->abort == abort_t::abort_none && ctx->loc_break != "") + { + break_ctxs_.push_back(ctx.get()); + emit_remove_local_vars(ctx); + ctx->abort = abort_t::abort_break; + emit_opcode(ctx, opcode::OP_jump, ctx->loc_break); + } + else + { + throw gsc::comp_error(stmt->loc, "illegal break statement"); + } +} + +void compiler::emit_stmt_continue(const gsc::context_ptr& ctx, const gsc::stmt_continue_ptr& stmt) +{ + if(can_break_ && ctx->abort == abort_t::abort_none && ctx->loc_continue != "") + { + continue_ctxs_.push_back(ctx.get()); + emit_remove_local_vars(ctx); + ctx->abort = abort_t::abort_continue; + emit_opcode(ctx, opcode::OP_jump, ctx->loc_continue); + } + else + { + throw gsc::comp_error(stmt->loc, "illegal continue statement"); + } +} + +void compiler::emit_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt) +{ + if(ctx->abort == abort_t::abort_none) + { + ctx->abort = abort_t::abort_return; + } + + if(stmt->expr.as_node->type == gsc::node_t::null) + { + emit_opcode(ctx, opcode::OP_End); + } + else + { + emit_expr(ctx, stmt->expr); + emit_opcode(ctx, opcode::OP_Return); + } +} + +void compiler::emit_expr(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr) +{ + switch(expr.as_node->type) + { + case gsc::node_t::expr_ternary: emit_expr_ternary(ctx, expr.as_ternary); break; + case gsc::node_t::expr_and: emit_expr_and(ctx, expr.as_and); break; + case gsc::node_t::expr_or: emit_expr_or(ctx, expr.as_or); break; + case gsc::node_t::expr_equality: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_inequality: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_less: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_greater: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_less_equal: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_greater_equal: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_bitwise_or: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_bitwise_and: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_bitwise_exor: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_shift_left: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_shift_right: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_add: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_sub: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_mult: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_div: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_mod: emit_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_complement: emit_expr_complement(ctx, expr.as_complement); break; + case gsc::node_t::expr_not: emit_expr_not(ctx, expr.as_not); break; + case gsc::node_t::expr_call: emit_expr_call(ctx, expr.as_call); break; + case gsc::node_t::expr_function: emit_expr_function(ctx, expr.as_function); break; + case gsc::node_t::expr_add_array: emit_expr_add_array(ctx, expr.as_add_array); break; + case gsc::node_t::expr_array: emit_array_variable(ctx, expr.as_array); break; + case gsc::node_t::expr_field: emit_field_variable(ctx, expr.as_field); break; + case gsc::node_t::expr_size: emit_expr_size(ctx, expr.as_size); break; + case gsc::node_t::data_thisthread: emit_opcode(ctx, opcode::OP_GetThisthread); break; + case gsc::node_t::data_empty_array: emit_opcode(ctx, opcode::OP_EmptyArray); break; + case gsc::node_t::data_undefined: emit_opcode(ctx, opcode::OP_GetUndefined); break; + case gsc::node_t::data_game: emit_opcode(ctx, opcode::OP_GetGame); break; + case gsc::node_t::data_self: emit_opcode(ctx, opcode::OP_GetSelf); break; + case gsc::node_t::data_anim: emit_opcode(ctx, opcode::OP_GetAnim); break; + case gsc::node_t::data_level: emit_opcode(ctx, opcode::OP_GetLevel); break; + case gsc::node_t::data_animation: emit_animation(ctx, expr.as_animation); break; + case gsc::node_t::data_animtree: emit_animtree(ctx, expr.as_animtree); break; + case gsc::node_t::data_name: emit_local_variable(ctx, expr.as_name); break; + case gsc::node_t::data_istring: emit_istring(ctx, expr.as_istring); break; + case gsc::node_t::data_string: emit_string(ctx, expr.as_string); break; + case gsc::node_t::data_color: emit_color(ctx, expr.as_color); break; + case gsc::node_t::data_vector: emit_vector(ctx, expr.as_vector); break; + case gsc::node_t::data_float: emit_float(ctx, expr.as_float); break; + case gsc::node_t::data_integer: emit_integer(ctx, expr.as_integer); break; + case gsc::node_t::data_false: emit_false(ctx, expr.as_false); break; + case gsc::node_t::data_true: emit_true(ctx, expr.as_true); break; + default: throw gsc::comp_error(expr.as_node->loc, "unknown expression"); break; + } +} + +void compiler::emit_expr_assign(const gsc::context_ptr& ctx, const gsc::expr_assign_ptr& expr) +{ + if(expr->type == gsc::node_t::expr_increment) + { + emit_variable_ref(ctx, expr->lvalue, false); + emit_opcode(ctx, opcode::OP_inc); + emit_opcode(ctx, opcode::OP_SetVariableField); + } + else if(expr->type == gsc::node_t::expr_decrement) + { + emit_variable_ref(ctx, expr->lvalue, false); + emit_opcode(ctx, opcode::OP_dec); + emit_opcode(ctx, opcode::OP_SetVariableField); + } + else if(expr->type == gsc::node_t::expr_assign_equal) + { + if(expr->rvalue.as_node->type == gsc::node_t::data_undefined) + { + emit_expr_clear_variable(ctx, expr->lvalue); + } + else + { + emit_expr(ctx, expr->rvalue); + emit_variable_ref(ctx, expr->lvalue, true); + } + } + else + { + emit_expr(ctx, expr->lvalue); + emit_expr(ctx, expr->rvalue); + + switch(expr->type) + { + case gsc::node_t::expr_assign_add: emit_opcode(ctx, opcode::OP_plus); break; + case gsc::node_t::expr_assign_sub: emit_opcode(ctx, opcode::OP_minus); break; + case gsc::node_t::expr_assign_mult: emit_opcode(ctx, opcode::OP_multiply); break; + case gsc::node_t::expr_assign_div: emit_opcode(ctx, opcode::OP_divide); break; + case gsc::node_t::expr_assign_mod: emit_opcode(ctx, opcode::OP_mod); break; + case gsc::node_t::expr_assign_shift_left: emit_opcode(ctx, opcode::OP_shift_left); break; + case gsc::node_t::expr_assign_shift_right: emit_opcode(ctx, opcode::OP_shift_right); break; + case gsc::node_t::expr_assign_bitwise_or: emit_opcode(ctx, opcode::OP_bit_or); break; + case gsc::node_t::expr_assign_bitwise_and: emit_opcode(ctx, opcode::OP_bit_and); break; + case gsc::node_t::expr_assign_bitwise_exor: emit_opcode(ctx, opcode::OP_bit_ex_or); break; + default: throw gsc::comp_error(expr->loc, "unknown assign operation"); break; + } + + emit_variable_ref(ctx, expr->lvalue, true); + } +} + +void compiler::emit_expr_ternary(const gsc::context_ptr& ctx, const gsc::expr_ternary_ptr& expr) +{ + auto else_loc = create_label(); + auto end_loc = create_label(); + + if(expr->cond.as_node->type == gsc::node_t::expr_not) + { + emit_expr(ctx, expr->cond.as_not->rvalue); + emit_opcode(ctx, opcode::OP_JumpOnTrue, else_loc); + } + else + { + emit_expr(ctx, expr->cond); + emit_opcode(ctx, opcode::OP_JumpOnFalse, else_loc); + } + + emit_expr(ctx, expr->lvalue); + emit_opcode(ctx, opcode::OP_jump, end_loc); + + insert_label(else_loc); + emit_expr(ctx, expr->rvalue); + insert_label(end_loc); +} + +void compiler::emit_expr_binary(const gsc::context_ptr& ctx, const gsc::expr_binary_ptr& expr) +{ + emit_expr(ctx, expr->lvalue); + emit_expr(ctx, expr->rvalue); + + switch(expr->type) + { + case gsc::node_t::expr_equality: emit_opcode(ctx, opcode::OP_equality); break; + case gsc::node_t::expr_inequality: emit_opcode(ctx, opcode::OP_inequality); break; + case gsc::node_t::expr_less: emit_opcode(ctx, opcode::OP_less); break; + case gsc::node_t::expr_greater: emit_opcode(ctx, opcode::OP_greater); break; + case gsc::node_t::expr_less_equal: emit_opcode(ctx, opcode::OP_less_equal); break; + case gsc::node_t::expr_greater_equal: emit_opcode(ctx, opcode::OP_greater_equal); break; + case gsc::node_t::expr_bitwise_or: emit_opcode(ctx, opcode::OP_bit_or); break; + case gsc::node_t::expr_bitwise_and: emit_opcode(ctx, opcode::OP_bit_and); break; + case gsc::node_t::expr_bitwise_exor: emit_opcode(ctx, opcode::OP_bit_ex_or); break; + case gsc::node_t::expr_shift_left: emit_opcode(ctx, opcode::OP_shift_left); break; + case gsc::node_t::expr_shift_right: emit_opcode(ctx, opcode::OP_shift_right); break; + case gsc::node_t::expr_add: emit_opcode(ctx, opcode::OP_plus); break; + case gsc::node_t::expr_sub: emit_opcode(ctx, opcode::OP_minus); break; + case gsc::node_t::expr_mult: emit_opcode(ctx, opcode::OP_multiply); break; + case gsc::node_t::expr_div: emit_opcode(ctx, opcode::OP_divide); break; + case gsc::node_t::expr_mod: emit_opcode(ctx, opcode::OP_mod); break; + default: throw gsc::comp_error(expr->loc, "unknown binary expression"); break; + } +} + +void compiler::emit_expr_isdefined(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& expr) +{ + emit_expr_arguments(ctx, expr); + emit_opcode(ctx, opcode::OP_IsDefined); +} + +void compiler::emit_expr_istrue(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& expr) +{ + emit_expr_arguments(ctx, expr); + emit_opcode(ctx, opcode::OP_IsTrue); +} + +void compiler::emit_expr_bool_not_after_and(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr) +{ + emit_expr(ctx, expr); + emit_opcode(ctx, opcode::OP_BoolNotAfterAnd); +} + +void compiler::emit_expr_and(const gsc::context_ptr& ctx, const gsc::expr_and_ptr& expr) +{ + auto label = create_label(); + + emit_expr(ctx, expr->lvalue); + emit_opcode(ctx, opcode::OP_JumpOnFalseExpr, label); + + if(expr->rvalue.as_node->type == gsc::node_t::expr_not) + { + emit_expr_bool_not_after_and(ctx, expr->rvalue.as_not->rvalue); + } + else + { + emit_expr(ctx, expr->rvalue); + emit_opcode(ctx, opcode::OP_CastBool); + } + + insert_label(label); +} + +void compiler::emit_expr_or(const gsc::context_ptr& ctx, const gsc::expr_or_ptr& expr) +{ + auto label = create_label(); + + emit_expr(ctx, expr->lvalue); + emit_opcode(ctx, opcode::OP_JumpOnTrueExpr, label); + + if(expr->rvalue.as_node->type == gsc::node_t::expr_not) + { + emit_expr_bool_not_after_and(ctx, expr->rvalue.as_not->rvalue); + } + else + { + emit_expr(ctx, expr->rvalue); + emit_opcode(ctx, opcode::OP_CastBool); + } + + insert_label(label); +} + +void compiler::emit_expr_complement(const gsc::context_ptr& ctx, const gsc::expr_complement_ptr& expr) +{ + emit_expr(ctx, expr->rvalue); + emit_opcode(ctx, opcode::OP_BoolComplement); +} + +void compiler::emit_expr_not(const gsc::context_ptr& ctx, const gsc::expr_not_ptr& expr) +{ + emit_expr(ctx, expr->rvalue); + emit_opcode(ctx, opcode::OP_BoolNot); +} + +void compiler::emit_expr_call(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr) +{ + if(expr->func.as_node->type == gsc::node_t::expr_call_pointer) + { + emit_expr_call_pointer(ctx, expr); + } + else + { + emit_expr_call_function(ctx, expr); + } +} + +void compiler::emit_expr_call_pointer(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr) +{ + bool thread = expr->thread; + bool child = expr->child; + bool method = expr->obj.as_node->type != gsc::node_t::null ? true : false; + bool builtin = builtin = expr->func.as_pointer->builtin; + std::uint32_t args = expr->func.as_pointer->args->list.size(); + + if(thread && child || thread && builtin || child && builtin) + throw gsc::comp_error(expr->loc, "function call have more than 1 type (thread, childthread, builtin)"); + + if(!thread && !child && !builtin) emit_opcode(ctx, opcode::OP_PreScriptCall); + + emit_expr_arguments(ctx, expr->func.as_pointer->args); + + if(method) emit_expr(ctx, expr->obj); + + emit_expr(ctx, expr->func.as_pointer->expr); + emit_expr_call_pointer_type(ctx, args, builtin, method, thread, child); +} + +void compiler::emit_expr_call_pointer_type(const gsc::context_ptr& ctx, int args, bool builtin, bool method, bool thread, bool child) +{ + if(builtin && !method) + { + emit_opcode(ctx, opcode::OP_CallBuiltinPointer, utils::string::va("%d", args)); + } + else if(builtin && method) + { + emit_opcode(ctx, opcode::OP_CallBuiltinMethodPointer, utils::string::va("%d", args)); + } + else if(thread && !method && !child) + { + emit_opcode(ctx, opcode::OP_ScriptThreadCallPointer, utils::string::va("%d", args)); + } + else if(thread && method && !child) + { + emit_opcode(ctx, opcode::OP_ScriptMethodThreadCallPointer, utils::string::va("%d", args)); + } + else if (child && !method && !thread) + { + emit_opcode(ctx, opcode::OP_ScriptChildThreadCallPointer, utils::string::va("%d", args)); + } + else if(child && method && !thread) + { + emit_opcode(ctx, opcode::OP_ScriptMethodChildThreadCallPointer, utils::string::va("%d", args)); + } + else + { + method ? emit_opcode(ctx, opcode::OP_ScriptMethodCallPointer) : emit_opcode(ctx, opcode::OP_ScriptFunctionCallPointer); + } +} + +void compiler::emit_expr_call_function(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr) +{ + if(expr->func.as_func->name->value == "isdefined") + { + emit_expr_isdefined(ctx, expr->func.as_func->args); + return; + } + else if(expr->func.as_func->name->value == "istrue") + { + emit_expr_isdefined(ctx, expr->func.as_func->args); + return; + } + + bool thread = expr->thread; + bool child = expr->child; + bool method = expr->obj.as_node->type != gsc::node_t::null ? true : false; + std::uint32_t args = expr->func.as_func->args->list.size(); + auto name = expr->func.as_func->name->value; + auto file = expr->func.as_func->file->value; + + bool builtin = false, far = false, local = false; + + if(file != "") far = true; + else + { + if(is_local_call(name)) local = true; + else if(method && is_builtin_method(name)) builtin = true; + else if(!method && is_builtin_func(name)) builtin = true; + else + { + for(const auto& inc : includes_) + { + for(const auto& fun : inc.funcs) + { + if(name == fun) + { + far = true; + file = inc.name; + break; + } + } + } + + if(!builtin && !far && !local) + throw gsc::comp_error(expr->loc, "unknown function call " + name); + } + } + + if(thread && child || thread && builtin || child && builtin) + throw gsc::comp_error(expr->loc, "function call have more than 1 type (thread, childthread, builtin)"); + + if(!thread && !child && !builtin && !(!method && args == 0)) + emit_opcode(ctx, opcode::OP_PreScriptCall); + + emit_expr_arguments(ctx, expr->func.as_func->args); + + if(method) emit_expr(ctx, expr->obj); + + if(builtin) emit_expr_call_function_builtin(ctx, name, args, method); + else if(local) emit_expr_call_function_local(ctx, name, args, method, thread, child); + else if(far) emit_expr_call_function_far(ctx, file, name, args, method, thread, child); +} + +void compiler::emit_expr_call_function_builtin(const gsc::context_ptr& ctx, const std::string& func, int args, bool method) +{ + if(method) + { + switch(args) + { + case 0: emit_opcode(ctx, opcode::OP_CallBuiltinMethod0, func); break; + case 1: emit_opcode(ctx, opcode::OP_CallBuiltinMethod1, func); break; + case 2: emit_opcode(ctx, opcode::OP_CallBuiltinMethod2, func); break; + case 3: emit_opcode(ctx, opcode::OP_CallBuiltinMethod3, func); break; + case 4: emit_opcode(ctx, opcode::OP_CallBuiltinMethod4, func); break; + case 5: emit_opcode(ctx, opcode::OP_CallBuiltinMethod5, func); break; + default: emit_opcode(ctx, opcode::OP_CallBuiltinMethod, { utils::string::va("%d", args), func }); break; + } + } + else + { + switch(args) + { + case 0: emit_opcode(ctx, opcode::OP_CallBuiltin0, func); break; + case 1: emit_opcode(ctx, opcode::OP_CallBuiltin1, func); break; + case 2: emit_opcode(ctx, opcode::OP_CallBuiltin2, func); break; + case 3: emit_opcode(ctx, opcode::OP_CallBuiltin3, func); break; + case 4: emit_opcode(ctx, opcode::OP_CallBuiltin4, func); break; + case 5: emit_opcode(ctx, opcode::OP_CallBuiltin5, func); break; + default: emit_opcode(ctx, opcode::OP_CallBuiltin, { utils::string::va("%d", args), func }); break; + } + } +} + +void compiler::emit_expr_call_function_local(const gsc::context_ptr& ctx, const std::string& func, int args, bool method, bool thread, bool child) +{ + if(thread && !method && !child) + { + emit_opcode(ctx, opcode::OP_ScriptLocalThreadCall, { func, utils::string::va("%d", args) }); + } + else if(thread && method && !child) + { + emit_opcode(ctx, opcode::OP_ScriptLocalMethodThreadCall, { func, utils::string::va("%d", args) }); + } + else if(child && !method && !thread) + { + emit_opcode(ctx, opcode::OP_ScriptLocalChildThreadCall, { func, utils::string::va("%d", args) }); + } + else if(child && method && !thread) + { + emit_opcode(ctx, opcode::OP_ScriptLocalMethodChildThreadCall, { func, utils::string::va("%d", args) }); + } + else if(method && !thread && !child) + { + emit_opcode(ctx, opcode::OP_ScriptLocalMethodCall, func); + } + else if(!thread && !child && !method && args == 0) + { + emit_opcode(ctx, opcode::OP_ScriptLocalFunctionCall2, func); + } + else if(!thread && !child && !method && args != 0) + { + emit_opcode(ctx, opcode::OP_ScriptLocalFunctionCall, func); + } +} + +void compiler::emit_expr_call_function_far(const gsc::context_ptr& ctx, const std::string& file, const std::string& func, int args, bool method, bool thread, bool child) +{ + if(thread && !method && !child) + { + emit_opcode(ctx, opcode::OP_ScriptFarThreadCall, { utils::string::va("%d", args), file, func }); + } + else if(thread && method && !child) + { + emit_opcode(ctx, opcode::OP_ScriptFarMethodThreadCall, { utils::string::va("%d", args), file, func }); + } + else if(child && !method && !thread) + { + emit_opcode(ctx, opcode::OP_ScriptFarChildThreadCall, { utils::string::va("%d", args), file, func }); + } + else if(child && method && !thread) + { + emit_opcode(ctx, opcode::OP_ScriptFarMethodChildThreadCall, { utils::string::va("%d", args), file, func }); + } + else if(!thread && !child && method) + { + emit_opcode(ctx, opcode::OP_ScriptFarMethodCall, { file, func }); + } + else if(!thread && !child && !method && args == 0) + { + emit_opcode(ctx, opcode::OP_ScriptFarFunctionCall2, { file, func }); + } + else if(!thread && !child && !method && args != 0) + { + emit_opcode(ctx, opcode::OP_ScriptFarFunctionCall, { file, func }); + } +} + +void compiler::emit_expr_arguments(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& args) +{ + std::reverse(args->list.begin(), args->list.end()); + + for(auto& arg : args->list) + { + emit_expr(ctx, arg); + } +} + +void compiler::emit_expr_function(const gsc::context_ptr& ctx, const gsc::expr_function_ptr& expr) +{ + bool far = false, local = false, builtin = false, method = false; + auto name = expr->name->value; + auto file = expr->file->value; + + if(file != "") + { + far = true; + } + else if(is_include_call(name, file)) + { + far = true; + } + else if(is_builtin_method(name)) + { + builtin = true; + method = true; + } + else if(is_builtin_func(name)) + { + builtin = true; + } + else if(is_local_call(name)) + { + local = true; + } + else + { + throw gsc::comp_error(expr->loc, "couldn't determine function reference type"); + } + + if(local) + { + emit_opcode(ctx, opcode::OP_GetLocalFunction, name); + } + else if(far) + { + emit_opcode(ctx, opcode::OP_GetFarFunction, { file, name } ); + } + else if(builtin && method) + { + emit_opcode(ctx, opcode::OP_GetBuiltinMethod, name); + } + else if(builtin && !method) + { + emit_opcode(ctx, opcode::OP_GetBuiltinFunction, name); + } +} + +void compiler::emit_expr_clear_variable(const gsc::context_ptr& ctx, const gsc::expr_ptr& lvalue) +{ + switch(lvalue.as_node->type) + { + case gsc::node_t::expr_array: + emit_expr(ctx, lvalue.as_array->key); + lvalue.as_array->obj.as_node->type == gsc::node_t::data_game ? emit_opcode(ctx, opcode::OP_GetGameRef) : emit_variable_ref(ctx, lvalue.as_array->obj, false); + emit_opcode(ctx, opcode::OP_ClearArray); + break; + case gsc::node_t::expr_field: + emit_object(ctx, lvalue.as_field->obj); + emit_opcode(ctx, opcode::OP_ClearFieldVariable,lvalue.as_field->field->value); + break; + case gsc::node_t::data_name: + emit_opcode(ctx, opcode::OP_GetUndefined); + emit_local_variable_ref(ctx, lvalue.as_name, true); + break; + default: + throw gsc::comp_error(lvalue.as_node->loc, "unknown clear variable lvalue"); + break; + } +} + +void compiler::emit_expr_add_array(const gsc::context_ptr& ctx, const gsc::expr_add_array_ptr& expr) +{ + if(expr->args->list.size() <= 0) + { + throw gsc::comp_error(expr->loc, "invalid empty add array. did u mean '[]' ?"); + } + + emit_opcode(ctx, opcode::OP_EmptyArray); + + for(const auto& arg : expr->args->list) + { + emit_expr(ctx, arg); + emit_opcode(ctx, opcode::OP_AddArray); + } +} + +void compiler::emit_expr_size(const gsc::context_ptr& ctx, const gsc::expr_size_ptr& expr) +{ + emit_variable(ctx, expr->obj); + emit_opcode(ctx, opcode::OP_size); +} + +void compiler::emit_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr, bool set) +{ + switch(expr.as_node->type) + { + case gsc::node_t::expr_array: emit_array_variable_ref(ctx, expr.as_array, set); break; + case gsc::node_t::expr_field: emit_field_variable_ref(ctx, expr.as_field, set); break; + case gsc::node_t::data_name: emit_local_variable_ref(ctx, expr.as_name, set); break; + default: throw gsc::comp_error(expr.as_node->loc, "invalid variable reference type."); break; + } +} + +void compiler::emit_array_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr, bool set) +{ + emit_expr(ctx, expr->key); + + switch(expr->obj.as_node->type) + { + case gsc::node_t::data_game: + emit_opcode(ctx, opcode::OP_GetGameRef); + emit_opcode(ctx, opcode::OP_EvalArrayRef); + if(set) emit_opcode(ctx, opcode::OP_SetVariableField); + break; + case gsc::node_t::expr_array: + case gsc::node_t::expr_field: + emit_variable_ref(ctx, expr->obj, false); + emit_opcode(ctx, opcode::OP_EvalArrayRef); + if(set) emit_opcode(ctx, opcode::OP_SetVariableField); + break; + case gsc::node_t::data_name: + { + if(!variable_initialized(ctx, expr->obj.as_name)) + { + initialize_variable(ctx, expr->obj.as_name); + emit_opcode(ctx, opcode::OP_EvalNewLocalArrayRefCached0, variable_create_index(ctx, expr->obj.as_name)); + + if(!set) + { + throw gsc::comp_error(expr->loc, "INTERNAL: VAR CREATED BUT NOT SET!"); + } + } + else if(variable_stack_index(ctx, expr->obj.as_name) == 0) + { + emit_opcode(ctx, opcode::OP_EvalLocalArrayRefCached0); + } + else + { + emit_opcode(ctx, opcode::OP_EvalLocalArrayRefCached, variable_access_index(ctx, expr->obj.as_name)); + } + + if(set) emit_opcode(ctx, opcode::OP_SetVariableField); + } + break; + case gsc::node_t::expr_call: + throw gsc::comp_error(expr->loc, "call result can't be referenced."); + break; + default: + throw gsc::comp_error(expr->loc, "unknown array object type"); + break; + } +} + +void compiler::emit_field_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr, bool set) +{ + const auto& field = expr->field->value; + + switch(expr->obj.as_node->type) + { + case gsc::node_t::data_level: + set ? emit_opcode(ctx, opcode::OP_SetLevelFieldVariableField, field) : emit_opcode(ctx, opcode::OP_EvalLevelFieldVariableRef, field); + break; + case gsc::node_t::data_anim: + set ? emit_opcode(ctx, opcode::OP_SetAnimFieldVariableField, field) : emit_opcode(ctx, opcode::OP_EvalAnimFieldVariableRef, field); + break; + case gsc::node_t::data_self: + set ? emit_opcode(ctx, opcode::OP_SetSelfFieldVariableField, field) : emit_opcode(ctx, opcode::OP_EvalSelfFieldVariableRef, field); + break; + case gsc::node_t::expr_array: + emit_array_variable(ctx, expr->obj.as_array); + emit_opcode(ctx, opcode::OP_CastFieldObject); + emit_opcode(ctx, opcode::OP_EvalFieldVariableRef, field); + if(set) emit_opcode(ctx, opcode::OP_SetVariableField); + break; + case gsc::node_t::expr_field: + emit_field_variable(ctx, expr->obj.as_field); + emit_opcode(ctx, opcode::OP_CastFieldObject); + emit_opcode(ctx, opcode::OP_EvalFieldVariableRef, field); + if(set) emit_opcode(ctx, opcode::OP_SetVariableField); + break; + case gsc::node_t::data_name: + emit_opcode(ctx, opcode::OP_EvalLocalVariableObjectCached, variable_access_index(ctx, expr->obj.as_name)); + emit_opcode(ctx, opcode::OP_EvalFieldVariableRef, field); + if(set) emit_opcode(ctx, opcode::OP_SetVariableField); + break; + case gsc::node_t::expr_call: + throw gsc::comp_error(expr->loc, "function call result can't be referenced"); + break; + default: + throw gsc::comp_error(expr->loc, "unknown field variable object type"); + break; + } +} + +void compiler::emit_local_variable_ref(const gsc::context_ptr& ctx, const gsc::name_ptr& expr, bool set) +{ + const auto itr = constants_.find(expr->value); + + if (itr != constants_.end()) + { + throw gsc::comp_error(expr->loc, "variable name already defined as constant " + expr->value); + } + + if(set) + { + if(!variable_initialized(ctx, expr)) + { + initialize_variable(ctx, expr); + emit_opcode(ctx, opcode::OP_SetNewLocalVariableFieldCached0, variable_create_index(ctx, expr)); + } + else if(variable_stack_index(ctx, expr) == 0) + { + emit_opcode(ctx, opcode::OP_SetLocalVariableFieldCached0); + } + else + { + emit_opcode(ctx, opcode::OP_SetLocalVariableFieldCached, variable_access_index(ctx, expr)); + } + } + else + { + auto index = variable_stack_index(ctx, expr); + + if(index == 0) + emit_opcode(ctx, opcode::OP_EvalLocalVariableRefCached0); + else + emit_opcode(ctx, opcode::OP_EvalLocalVariableRefCached, variable_access_index(ctx, expr)); + } +} + +void compiler::emit_variable(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr) +{ + // for obj.size + switch(expr.as_node->type) + { + case gsc::node_t::expr_array: emit_array_variable(ctx, expr.as_array); break; + case gsc::node_t::expr_field: emit_field_variable(ctx, expr.as_field); break; + case gsc::node_t::data_name: emit_local_variable(ctx, expr.as_name); break; + case gsc::node_t::expr_call: emit_expr_call(ctx, expr.as_call); break; + default: throw gsc::comp_error(expr.as_node->loc, "invalid variable type."); break; + } +} + +void compiler::emit_array_variable(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr) +{ + emit_expr(ctx, expr->key); + + if(expr->obj.as_node->type == gsc::node_t::data_name) + { + emit_opcode(ctx, opcode::OP_EvalLocalArrayCached, variable_access_index(ctx, expr->obj.as_name)); + } + else + { + emit_expr(ctx, expr->obj); + emit_opcode(ctx, opcode::OP_EvalArray); + } +} + +void compiler::emit_field_variable(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr) +{ + const auto& field = expr->field->value; + + switch(expr->obj.as_node->type) + { + case gsc::node_t::data_level: + emit_opcode(ctx, opcode::OP_EvalLevelFieldVariable, field); + break; + case gsc::node_t::data_anim: + emit_opcode(ctx, opcode::OP_EvalAnimFieldVariable, field); + break; + case gsc::node_t::data_self: + emit_opcode(ctx, opcode::OP_EvalSelfFieldVariable, field); + break; + case gsc::node_t::expr_array: + emit_array_variable(ctx, expr->obj.as_array); + emit_opcode(ctx, opcode::OP_CastFieldObject); + emit_opcode(ctx, opcode::OP_EvalFieldVariable, field); + break; + case gsc::node_t::expr_field: + emit_field_variable(ctx, expr->obj.as_field); + emit_opcode(ctx, opcode::OP_CastFieldObject); + emit_opcode(ctx, opcode::OP_EvalFieldVariable, field); + break; + case gsc::node_t::expr_call: + emit_expr_call(ctx, expr->obj.as_call); + emit_opcode(ctx, opcode::OP_CastFieldObject); + emit_opcode(ctx, opcode::OP_EvalFieldVariable, field); + break; + case gsc::node_t::data_name: + emit_opcode(ctx, opcode::OP_EvalLocalVariableObjectCached, variable_access_index(ctx, expr->obj.as_name)); + emit_opcode(ctx, opcode::OP_EvalFieldVariable, field); + break; + default: + throw gsc::comp_error(expr->loc, "unknown field variable object type"); + break; + } +} + +void compiler::emit_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr) +{ + // is constant ( should only allow: string, loc string, number, vector) + const auto itr = constants_.find(expr->value); + + if (itr != constants_.end()) + { + const auto& value = itr->second; + emit_expr(ctx, value); + return; + } + + // is local var + auto index = variable_stack_index(ctx, expr); + + switch(index) + { + case 0: emit_opcode(ctx, opcode::OP_EvalLocalVariableCached0); break; + case 1: emit_opcode(ctx, opcode::OP_EvalLocalVariableCached1); break; + case 2: emit_opcode(ctx, opcode::OP_EvalLocalVariableCached2); break; + case 3: emit_opcode(ctx, opcode::OP_EvalLocalVariableCached3); break; + case 4: emit_opcode(ctx, opcode::OP_EvalLocalVariableCached4); break; + case 5: emit_opcode(ctx, opcode::OP_EvalLocalVariableCached5); break; + default: emit_opcode(ctx, opcode::OP_EvalLocalVariableCached, variable_access_index(ctx, expr)); break; + } +} + +void compiler::emit_clear_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr) +{ + auto index = variable_stack_index(ctx, expr); + + if(index == 0) + { + emit_opcode(ctx, opcode::OP_ClearLocalVariableFieldCached0); + } + else + { + emit_opcode(ctx, opcode::OP_ClearLocalVariableFieldCached, variable_access_index(ctx, expr)); + } +} + +void compiler::emit_create_local_vars(const gsc::context_ptr& ctx) +{ + if ( ctx->local_vars_create_count != ctx->local_vars_public_count ) + { + for(auto i = ctx->local_vars_create_count; i < ctx->local_vars_public_count; i++) + { + auto data = utils::string::va("%d", ctx->local_vars.at(i).create); + emit_opcode(ctx, opcode::OP_CreateLocalVariable, data); + ctx->local_vars.at(i).init = true; + } + ctx->local_vars_create_count = ctx->local_vars_public_count; + } +} + +void compiler::emit_remove_local_vars(const gsc::context_ptr& ctx) +{ + if(ctx->abort == abort_t::abort_none) + { + auto count = ctx->local_vars_create_count - ctx->local_vars_public_count; + + if(count > 0) + { + auto data = utils::string::va("%d", count); + emit_opcode(ctx, opcode::OP_RemoveLocalVariables, data); + } + } +} + +void compiler::emit_object(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr) +{ + switch(expr.as_node->type) + { + case gsc::node_t::data_level: + emit_opcode(ctx, opcode::OP_GetLevelObject); + break; + case gsc::node_t::data_anim: + emit_opcode(ctx, opcode::OP_GetAnimObject); + break; + case gsc::node_t::data_self: + emit_opcode(ctx, opcode::OP_GetSelfObject); + break; + case gsc::node_t::data_name: + emit_opcode(ctx, opcode::OP_EvalLocalVariableObjectCached, variable_access_index(ctx, expr.as_name)); + break; + case gsc::node_t::expr_call: + emit_expr_call(ctx, expr.as_call); + emit_opcode(ctx, opcode::OP_CastFieldObject); + break; + case gsc::node_t::expr_array: + emit_array_variable(ctx, expr.as_array); + emit_opcode(ctx, opcode::OP_CastFieldObject); + break; + case gsc::node_t::expr_field: + emit_field_variable(ctx, expr.as_field); + emit_opcode(ctx, opcode::OP_CastFieldObject); + break; + default: + throw gsc::comp_error(expr.as_node->loc, "unknown object type"); + break; + } +} + +void compiler::emit_animtree(const gsc::context_ptr& ctx, const gsc::animtree_ptr& animtree) +{ + if(animtrees_.size() == 0) + { + throw gsc::comp_error( animtree->loc, "trying to use animtree without specified using animtree"); + } + + auto& tree = animtrees_.back(); + + if(tree.loaded) + { + emit_opcode(ctx, opcode::OP_GetAnimTree, "''"); + } + else + { + emit_opcode(ctx, opcode::OP_GetAnimTree, tree.name); + tree.loaded = true; + } +} + +void compiler::emit_animation(const gsc::context_ptr& ctx, const gsc::animation_ptr& animation) +{ + if(animtrees_.size() == 0) + { + throw gsc::comp_error(animation->loc, "trying to use animation without specified using animtree"); + } + + auto& tree = animtrees_.back(); + + if(tree.loaded) + { + emit_opcode(ctx, opcode::OP_GetAnimation, { "''", animation->value }); + } + else + { + emit_opcode(ctx, opcode::OP_GetAnimation, { tree.name, animation->value }); + tree.loaded = true; + } +} + +void compiler::emit_istring(const gsc::context_ptr& ctx, const gsc::istring_ptr& str) +{ + emit_opcode(ctx, opcode::OP_GetIString, str->value); +} + +void compiler::emit_string(const gsc::context_ptr& ctx, const gsc::string_ptr& str) +{ + emit_opcode(ctx, opcode::OP_GetString, str->value); +} + +void compiler::emit_color(const gsc::context_ptr& ctx, const gsc::color_ptr& color) +{ + std::vector data; + std::string x, y, z; + + if(color->value.size() == 3) + { + x = "0x" + color->value.substr(0, 1) + color->value.substr(0, 1); + y = "0x" + color->value.substr(1, 1) + color->value.substr(1, 1); + z = "0x" + color->value.substr(2, 1) + color->value.substr(2, 1); + } + else + { + x = "0x" + color->value.substr(0, 2); + y = "0x" + color->value.substr(2, 2); + z = "0x" + color->value.substr(4, 2); + } + + data.push_back(gsc::utils::string::hex_to_dec(x.data())); + data.push_back(gsc::utils::string::hex_to_dec(y.data())); + data.push_back(gsc::utils::string::hex_to_dec(z.data())); + emit_opcode(ctx, opcode::OP_GetVector, data); +} + +void compiler::emit_vector(const gsc::context_ptr& ctx, const gsc::vector_ptr& vec) +{ + std::vector data; + + bool expr = false; + + if(vec->x.as_node->type == gsc::node_t::data_integer) + data.push_back(vec->x.as_integer->value); + else if(vec->x.as_node->type == gsc::node_t::data_float) + data.push_back(vec->x.as_float->value); + else expr = true; + + if(vec->y.as_node->type == gsc::node_t::data_integer) + data.push_back(vec->y.as_integer->value); + else if(vec->y.as_node->type == gsc::node_t::data_float) + data.push_back(vec->y.as_float->value); + else expr = true; + + if(vec->z.as_node->type == gsc::node_t::data_integer) + data.push_back(vec->z.as_integer->value); + else if(vec->z.as_node->type == gsc::node_t::data_float) + data.push_back(vec->z.as_float->value); + else expr = true; + + if(!expr) + { + emit_opcode(ctx, opcode::OP_GetVector, data); + } + else + { + emit_expr(ctx, vec->z); + emit_expr(ctx, vec->y); + emit_expr(ctx, vec->x); + emit_opcode(ctx, opcode::OP_vector); + } +} + +void compiler::emit_float(const gsc::context_ptr& ctx, const gsc::float_ptr& num) +{ + emit_opcode(ctx, opcode::OP_GetFloat, num->value); +} + +void compiler::emit_integer(const gsc::context_ptr& ctx, const gsc::integer_ptr& num) +{ + auto value = std::atoi(num->value.data()); + + if(value == 0) + { + emit_opcode(ctx, opcode::OP_GetZero); + } + else if(value > 0 && value < 256) + { + emit_opcode(ctx, opcode::OP_GetByte, num->value); + } + else if(value < 0 && value > -256) + { + emit_opcode(ctx, opcode::OP_GetNegByte, num->value.substr(1)); + } + else if(value > 0 && value < 65536) + { + emit_opcode(ctx, opcode::OP_GetUnsignedShort, num->value); + } + else if(value < 0 && value > -65536) + { + emit_opcode(ctx, opcode::OP_GetNegUnsignedShort, num->value.substr(1)); + } + else + { + emit_opcode(ctx, opcode::OP_GetInteger, num->value); + } +} + +void compiler::emit_false(const gsc::context_ptr& ctx, const gsc::false_ptr& expr) +{ + emit_opcode(ctx, opcode::OP_GetZero); +} + +void compiler::emit_true(const gsc::context_ptr& ctx, const gsc::true_ptr& expr) +{ + emit_opcode(ctx, opcode::OP_GetByte, "1"); +} + +void compiler::emit_opcode(const gsc::context_ptr& ctx, opcode op) +{ + function_->instructions.push_back(std::make_unique()); + + auto& inst = function_->instructions.back(); + inst->opcode = static_cast(op); + inst->size = opcode_size(std::uint8_t(op)); + inst->index = index_; + + index_ += inst->size; +} + +void compiler::emit_opcode(const gsc::context_ptr& ctx, opcode op, const std::string& data) +{ + function_->instructions.push_back(std::make_unique()); + + auto& inst = function_->instructions.back(); + inst->opcode = static_cast(op); + inst->size = opcode_size(std::uint8_t(op)); + inst->index = index_; + inst->data.push_back(data); + + index_ += inst->size; +} + +void compiler::emit_opcode(const gsc::context_ptr& ctx, opcode op, const std::vector& data) +{ + function_->instructions.push_back(std::make_unique()); + + auto& inst = function_->instructions.back(); + inst->opcode = static_cast(op); + inst->size = opcode_size(std::uint8_t(op)); + inst->index = index_; + inst->data = data; + + index_ += inst->size; +} + +void compiler::process_thread(const gsc::context_ptr& ctx, const gsc::thread_ptr& thread) +{ + process_parameters(ctx, thread->params); + process_stmt_list(ctx, thread->block); +} + +void compiler::process_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params) +{ + for(const auto& param : params->list) + { + register_variable(ctx, param->value); + } +} + +void compiler::process_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt) +{ + switch (stmt.as_node->type) + { + case gsc::node_t::stmt_list: process_stmt_list(ctx, stmt.as_list); break; + case gsc::node_t::stmt_assign: process_expr(ctx, stmt.as_assign->expr->lvalue); break; + case gsc::node_t::stmt_waittill: process_stmt_waittill(ctx, stmt.as_waittill); break; + case gsc::node_t::stmt_if: process_stmt_if(ctx, stmt.as_if); break; + case gsc::node_t::stmt_ifelse: process_stmt_ifelse(ctx, stmt.as_ifelse); break; + case gsc::node_t::stmt_while: process_stmt_while(ctx, stmt.as_while); break; + case gsc::node_t::stmt_for: process_stmt_for(ctx, stmt.as_for); break; + case gsc::node_t::stmt_foreach: process_stmt_foreach(ctx, stmt.as_foreach); break; + case gsc::node_t::stmt_switch: process_stmt_switch(ctx, stmt.as_switch); break; + case gsc::node_t::stmt_break: process_stmt_break(ctx, stmt.as_break); break; + case gsc::node_t::stmt_continue: process_stmt_continue(ctx, stmt.as_continue); break; + case gsc::node_t::stmt_return: process_stmt_return(ctx, stmt.as_return); break; + default: break; + } +} + +void compiler::process_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt) +{ + for (const auto& entry : stmt->stmts) + { + process_stmt(ctx, entry); + } +} + +void compiler::process_expr(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr) +{ + if(expr.as_node->type == gsc::node_t::data_name) + { + register_variable(ctx, expr.as_name->value); + } + else if(expr.as_node->type == gsc::node_t::expr_array) + { + process_expr(ctx, expr.as_array->obj); + } +} + +void compiler::process_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt) +{ + for(const auto& arg : stmt->args->list) + { + register_variable(ctx, arg.as_name->value); + } +} + +void compiler::process_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt) +{ + stmt->ctx = std::make_unique(); + + ctx->copy(stmt->ctx); + process_stmt(stmt->ctx, stmt->stmt); + + std::vector childs({ stmt->ctx.get() }); + ctx->merge(childs); +} + +void compiler::process_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt) +{ + std::vector childs; + auto abort = abort_t::abort_return; + + stmt->ctx_if = std::make_unique(); + stmt->ctx_else = std::make_unique(); + + ctx->copy(stmt->ctx_if); + process_stmt(stmt->ctx_if, stmt->stmt_if); + + if(stmt->ctx_if->abort <= abort_t::abort_return) + { + abort = stmt->ctx_if->abort; + if(abort == abort_t::abort_none) + childs.push_back(stmt->ctx_if.get()); + } + + ctx->copy(stmt->ctx_else); + process_stmt(stmt->ctx_else, stmt->stmt_else); + + if(stmt->ctx_else->abort <= abort) + { + abort = stmt->ctx_else->abort; + if(abort == abort_t::abort_none) + childs.push_back(stmt->ctx_else.get()); + } + + if(ctx->abort == abort_t::abort_none) + ctx->abort = abort; + + ctx->append(childs); + ctx->merge(childs); +} + +void compiler::process_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt) +{ + bool const_cond = is_constant_condition(stmt->expr); + + auto old_breaks = break_ctxs_; + auto old_continues = continue_ctxs_; + break_ctxs_.clear(); + continue_ctxs_.clear(); + + stmt->ctx = std::make_unique(); + + ctx->copy(stmt->ctx); + process_stmt(stmt->ctx, stmt->stmt); + + continue_ctxs_.push_back(stmt->ctx.get()); + + for(auto i = 0; i < continue_ctxs_.size(); i++) + ctx->append({continue_ctxs_.at(i)}); + + if(const_cond) ctx->append(break_ctxs_); + + ctx->merge({stmt->ctx.get()}); + + break_ctxs_ = old_breaks; + continue_ctxs_ = old_continues; +} + +void compiler::process_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt) +{ + bool const_cond = is_constant_condition(stmt->expr); + + stmt->ctx = std::make_unique(); + stmt->ctx_post = std::make_unique(); + + process_stmt(ctx, stmt->pre_expr); + + auto old_breaks = break_ctxs_; + auto old_continues = continue_ctxs_; + break_ctxs_.clear(); + continue_ctxs_.clear(); + + ctx->copy(stmt->ctx); + ctx->copy(stmt->ctx_post); + + process_stmt(stmt->ctx, stmt->stmt); + + continue_ctxs_.push_back(stmt->ctx.get()); + + for(auto i = 0; i < continue_ctxs_.size(); i++) + ctx->append({continue_ctxs_.at(i)}); + + process_stmt(stmt->ctx_post, stmt->post_expr); + + ctx->append({ stmt->ctx_post.get() }); + ctx->merge({ stmt->ctx_post.get() }); + + if(const_cond) ctx->append(break_ctxs_); + + ctx->merge({stmt->ctx.get()}); + + break_ctxs_ = old_breaks; + continue_ctxs_ = old_continues; +} + +void compiler::process_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt) +{ + auto array_name = utils::string::va("temp_%d", ++label_idx_); + auto key_name = utils::string::va("temp_%d", ++label_idx_); + + stmt->array = expr_ptr(std::make_unique(stmt->loc, array_name)); + + if(!stmt->use_key) + stmt->key_expr = expr_ptr(std::make_unique(stmt->loc, key_name)); + + key_name = stmt->key_expr.as_name->value; + + // calculate variables + + stmt->ctx = std::make_unique(); + stmt->ctx_post = std::make_unique(); + + // calculate pre_expr variables + process_expr(ctx, stmt->array); + + auto old_breaks = break_ctxs_; + auto old_continues = continue_ctxs_; + break_ctxs_.clear(); + continue_ctxs_.clear(); + + ctx->copy(stmt->ctx); + ctx->copy(stmt->ctx_post); + + // calculate stmt variables & add missing array access as first stmt + process_expr(stmt->ctx, stmt->value_expr); + process_stmt(stmt->ctx, stmt->stmt); + + continue_ctxs_.push_back(stmt->ctx.get()); + + for(auto i = 0; i < continue_ctxs_.size(); i++) + ctx->append({continue_ctxs_.at(i)}); + + process_expr(stmt->ctx_post, stmt->key_expr); + + ctx->append({ stmt->ctx_post.get() }); + ctx->merge({ stmt->ctx_post.get() }); + ctx->merge({stmt->ctx.get()}); + + break_ctxs_ = old_breaks; + continue_ctxs_ = old_continues; +} + +void compiler::process_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt) +{ + auto stmt_list = std::make_unique(stmt->stmt->loc); + auto current_case = gsc::stmt_ptr(nullptr); + + auto num = stmt->stmt->stmts.size(); + + for(auto i = 0; i < num; i++) + { + auto& entry = stmt->stmt->stmts[0]; + + if(entry.as_node->type == gsc::node_t::stmt_case || entry.as_node->type == gsc::node_t::stmt_default) + { + if(current_case.as_node != nullptr) + { + stmt_list->stmts.push_back(std::move(current_case)); + } + + current_case = std::move(stmt->stmt->stmts[0]); + stmt->stmt->stmts.erase(stmt->stmt->stmts.begin()); + } + else + { + if(current_case.as_node != nullptr) + { + if(current_case.as_node->type == gsc::node_t::stmt_case) + { + current_case.as_case->stmt->stmts.push_back(std::move(entry)); + stmt->stmt->stmts.erase(stmt->stmt->stmts.begin()); + } + else + { + current_case.as_default->stmt->stmts.push_back(std::move(entry)); + stmt->stmt->stmts.erase(stmt->stmt->stmts.begin()); + } + } + else + { + throw gsc::comp_error(entry.as_node->loc, "missing case statement"); + } + } + } + + if(current_case.as_node != nullptr) + { + stmt_list->stmts.push_back(std::move(current_case)); + } + + // calculate variables + stmt->ctx = std::make_unique(); + std::vector childs; + auto abort = abort_t::abort_return; + bool has_default = false; + gsc::context* default_ctx = nullptr; + auto old_breaks = break_ctxs_; + break_ctxs_.clear(); + + for(auto i = 0; i < stmt_list->stmts.size(); i++) + { + auto& entry = stmt_list->stmts[i]; + + if(entry.as_node->type == gsc::node_t::stmt_case) + { + entry.as_case->ctx = std::make_unique(); + ctx->copy(entry.as_case->ctx); + process_stmt_list(entry.as_case->ctx, entry.as_case->stmt); + + if (entry.as_case->ctx->abort != abort_t::abort_none) + { + if (entry.as_case->ctx->abort == abort_t::abort_break ) + { + entry.as_case->ctx->abort = abort_t::abort_none; + abort = abort_t::abort_none; + childs.push_back(entry.as_case->ctx.get()); + } + else if (entry.as_case->ctx->abort <= abort ) + { + abort = entry.as_case->ctx->abort; + } + } + } + else if(entry.as_node->type == gsc::node_t::stmt_default) + { + entry.as_default->ctx = std::make_unique(); + ctx->copy(entry.as_default->ctx); + process_stmt_list(entry.as_default->ctx, entry.as_default->stmt); + has_default = true; + default_ctx = entry.as_default->ctx.get(); + + if (entry.as_default->ctx->abort != abort_t::abort_none) + { + if (entry.as_default->ctx->abort == abort_t::abort_break ) + { + entry.as_default->ctx->abort = abort_t::abort_none; + abort = abort_t::abort_none; + childs.push_back(entry.as_default->ctx.get()); + } + else if (entry.as_default->ctx->abort <= abort ) + { + abort = entry.as_default->ctx->abort; + } + } + } + } + + stmt->stmt =std::move(stmt_list); + + if(has_default) + { + if(default_ctx->abort == abort_t::abort_none) + { + break_ctxs_.push_back(default_ctx); + + if(ctx->abort == abort_t::abort_none) + ctx->abort = abort; + } + + ctx->append(break_ctxs_); + ctx->merge(childs); + } + + break_ctxs_ = old_breaks; +} + +void compiler::process_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt) +{ + if(ctx->abort == abort_t::abort_none) + { + break_ctxs_.push_back(ctx.get()); + ctx->abort = abort_t::abort_break; + } +} + +void compiler::process_stmt_continue(const gsc::context_ptr& ctx, const gsc::stmt_continue_ptr& stmt) +{ + if(ctx->abort == abort_t::abort_none) + { + continue_ctxs_.push_back(ctx.get()); + ctx->abort = abort_t::abort_continue; + } +} + +void compiler::process_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt) +{ + if(ctx->abort == abort_t::abort_none) + { + ctx->abort = abort_t::abort_return; + } +} + +void compiler::register_variable(const gsc::context_ptr& ctx, const std::string& name) +{ + auto it = std::find_if(ctx->local_vars.begin(), ctx->local_vars.end(), + [&](const gsc::local_var& v) { return v.name == name; }); + + if(it == ctx->local_vars.end()) + { + auto found = false; + for(std::size_t i = 0; i < local_stack_.size(); i++) + { + if(local_stack_[i] == name) + { + ctx->local_vars.push_back({ name, static_cast(i), false }); + found = true; + break; + } + } + + if(!found) + { + ctx->local_vars.push_back({ name, stack_idx_, false }); + local_stack_.push_back(name); + stack_idx_++; + } + } +} + +void compiler::initialize_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& name) +{ + for(std::uint32_t i = 0; i < ctx->local_vars.size(); i++) + { + if(ctx->local_vars[i].name == name->value) + { + if(!ctx->local_vars[i].init) + { + for(std::uint32_t j = 0; j < i; j++) + { + if(!ctx->local_vars[j].init) + { + emit_opcode(ctx, opcode::OP_CreateLocalVariable, utils::string::va("%d", ctx->local_vars[j].create)); + ctx->local_vars[j].init = true; + //ctx->local_vars_create_count++; + } + } + ctx->local_vars[i].init = true; + ctx->local_vars_create_count = i + 1; + return; + } + } + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not found."); +} + +void compiler::create_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& name) +{ + for(std::size_t i = 0; i < ctx->local_vars.size(); i++) + { + auto& var = ctx->local_vars.at(i); + if(var.name == name->value) + { + if(!var.init) + { + emit_opcode(ctx, opcode::OP_CreateLocalVariable, utils::string::va("%d", var.create)); + var.init = true; + ctx->local_vars_create_count++; + } + return; + } + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_stack_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::uint8_t +{ + for(std::size_t i = 0; i < ctx->local_vars.size(); i++) + { + if(ctx->local_vars[i].name == name->value) + { + if(ctx->local_vars.at(i).init) + { + return ctx->local_vars_create_count - 1 - i; + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not initialized."); + } + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_create_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::string +{ + for(std::size_t i = 0; i < ctx->local_vars.size(); i++) + { + if(ctx->local_vars[i].name == name->value) + return utils::string::va("%d", ctx->local_vars[i].create); + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_access_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::string +{ + for(std::size_t i = 0; i < ctx->local_vars.size(); i++) + { + if(ctx->local_vars[i].name == name->value) + { + if(ctx->local_vars.at(i).init) + { + return utils::string::va("%d", ctx->local_vars_create_count - 1 - i); + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not initialized."); + } + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_initialized(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> bool +{ + for(std::size_t i = 0; i < ctx->local_vars.size(); i++) + { + if(ctx->local_vars[i].name == name->value) + { + return ctx->local_vars.at(i).init; + } + } + + throw gsc::comp_error(name->loc, "local variable '" + name->value + "' not found."); +} + +auto compiler::is_include_call(const std::string& name, std::string& file) -> bool +{ + for(const auto& inc : includes_) + { + for(const auto& fun : inc.funcs) + { + if(name == fun) + { + file = inc.name; + return true; + } + } + } + + return false; +} + +auto compiler::is_local_call(const std::string& name) -> bool +{ + for(const auto& f : local_functions_) + { + if(f == name) return true; + } + + return false; +} + +auto compiler::is_builtin_call(const std::string& name) -> bool +{ + if(is_builtin_func(name)) return true; + + if(is_builtin_method(name)) return true; + + return false; +} + +auto compiler::is_builtin_func(const std::string& name) -> bool +{ + return resolver::find_function(name); +} +auto compiler::is_builtin_method(const std::string& name) -> bool +{ + return resolver::find_method(name); +} + +auto compiler::is_constant_condition(const gsc::expr_ptr& expr) -> bool +{ + switch(expr.as_node->type) + { + case gsc::node_t::null: + case gsc::node_t::data_true: + return true; + case gsc::node_t::data_false: + throw gsc::comp_error(expr.as_node->loc, "condition can't be always false!"); + case gsc::node_t::data_integer: + { + auto num = std::stoi(expr.as_integer->value); + if(num != 0) + return true; + else + throw gsc::comp_error(expr.as_node->loc, "condition can't be always false!"); + } + default: + break; + } + + return false; +} + +auto compiler::create_label() -> std::string +{ + label_idx_++; + auto name = utils::string::va("loc_%d", label_idx_); + return name; +} + +auto compiler::insert_label() -> std::string +{ + const auto itr = function_->labels.find(index_); + + if (itr != function_->labels.end()) + { + return itr->second; + } + else + { + label_idx_++; + auto name = utils::string::va("loc_%d", label_idx_); + function_->labels.insert({index_, name}); + return name; + } +} + +void compiler::insert_label(const std::string& name) +{ + const auto itr = function_->labels.find(index_); + + if (itr != function_->labels.end()) + { + for(auto& inst : function_->instructions) + { + switch (opcode(inst->opcode)) + { + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + case opcode::OP_jump: + case opcode::OP_jumpback: + case opcode::OP_switch: + if(inst->data[0] == name) + inst->data[0] = itr->second; + break; + case opcode::OP_endswitch: + default: + break; + } + } + } + else + { + function_->labels.insert({index_, name}); + } +} + +auto compiler::map_known_includes(const std::string& include) -> bool +{ + return false; +} + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/compiler.hpp b/src/s4/xsk/compiler.hpp new file mode 100644 index 00000000..8893b2b7 --- /dev/null +++ b/src/s4/xsk/compiler.hpp @@ -0,0 +1,152 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#pragma once + +namespace xsk::gsc::s4 +{ + +enum class opcode : std::uint8_t; + +class compiler : public gsc::compiler +{ + std::string filename_; + std::vector assembly_; + gsc::function_ptr function_; + std::uint32_t index_; + std::uint32_t label_idx_; + std::uint8_t stack_idx_; + std::vector local_stack_; + std::vector local_functions_; + std::vector includes_; + std::vector animtrees_; + std::unordered_map constants_; + std::function(const std::string&)> callback_readf_; + std::vector break_ctxs_; + std::vector continue_ctxs_; + bool can_break_; + bool can_continue_; + +public: + auto output() -> std::vector; + void compile(const std::string& file, std::vector& data); + void set_readf_callback(std::function(const std::string&)> func); + +private: + auto parse_buffer(const std::string& file, std::vector& data) -> gsc::program_ptr; + auto parse_file(const std::string& file) -> gsc::program_ptr; + void compile_program(const gsc::program_ptr& program); + void emit_include(const gsc::include_ptr& include); + void emit_define(const gsc::define_ptr& define); + void emit_usingtree(const gsc::usingtree_ptr& animtree); + void emit_constant(const gsc::constant_ptr& constant); + void emit_thread(const gsc::thread_ptr& thread); + void emit_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params); + void emit_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt, bool last); + void emit_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt, bool last); + void emit_stmt_call(const gsc::context_ptr& ctx, const gsc::stmt_call_ptr& stmt); + void emit_stmt_assign(const gsc::context_ptr& ctx, const gsc::stmt_assign_ptr& stmt); + void emit_stmt_endon(const gsc::context_ptr& ctx, const gsc::stmt_endon_ptr& stmt); + void emit_stmt_notify(const gsc::context_ptr& ctx, const gsc::stmt_notify_ptr& stmt); + void emit_stmt_wait(const gsc::context_ptr& ctx, const gsc::stmt_wait_ptr& stmt); + void emit_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt); + void emit_stmt_waittillmatch(const gsc::context_ptr& ctx, const gsc::stmt_waittillmatch_ptr& stmt); + void emit_stmt_waittillframeend(const gsc::context_ptr& ctx, const gsc::stmt_waittillframeend_ptr& stmt); + void emit_stmt_waitframe(const gsc::context_ptr& ctx, const gsc::stmt_waitframe_ptr& stmt); + void emit_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt, bool last); + void emit_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt, bool last); + void emit_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt); + void emit_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt); + void emit_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt); + void emit_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt); + void emit_stmt_case(const gsc::context_ptr& ctx, const gsc::stmt_case_ptr& stmt); + void emit_stmt_default(const gsc::context_ptr& ctx, const gsc::stmt_default_ptr& stmt); + void emit_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt); + void emit_stmt_continue(const gsc::context_ptr& ctx, const gsc::stmt_continue_ptr& stmt); + void emit_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt); + void emit_expr(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr); + void emit_expr_assign(const gsc::context_ptr& ctx, const gsc::expr_assign_ptr& expr); + void emit_expr_ternary(const gsc::context_ptr& ctx, const gsc::expr_ternary_ptr& expr); + void emit_expr_binary(const gsc::context_ptr& ctx, const gsc::expr_binary_ptr& expr); + void emit_expr_isdefined(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& expr); + void emit_expr_istrue(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& expr); + void emit_expr_bool_not_after_and(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr); + void emit_expr_and(const gsc::context_ptr& ctx, const gsc::expr_and_ptr& expr); + void emit_expr_or(const gsc::context_ptr& ctx, const gsc::expr_or_ptr& expr); + void emit_expr_complement(const gsc::context_ptr& ctx, const gsc::expr_complement_ptr& expr); + void emit_expr_not(const gsc::context_ptr& ctx, const gsc::expr_not_ptr& expr); + void emit_expr_call(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr); + void emit_expr_call_pointer(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr); + void emit_expr_call_pointer_type(const gsc::context_ptr& ctx, int args, bool builtin, bool method, bool thread, bool child); + void emit_expr_call_function(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr); + void emit_expr_call_function_builtin(const gsc::context_ptr& ctx, const std::string& func, int args, bool method); + void emit_expr_call_function_local(const gsc::context_ptr& ctx, const std::string& func, int args, bool method, bool thread, bool child); + void emit_expr_call_function_far(const gsc::context_ptr& ctx, const std::string& file, const std::string& func, int args, bool method, bool thread, bool child); + void emit_expr_arguments(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& arg_list); + void emit_expr_function(const gsc::context_ptr& ctx, const gsc::expr_function_ptr& node); + void emit_expr_clear_variable(const gsc::context_ptr& ctx, const gsc::expr_ptr& lvalue); + void emit_expr_add_array(const gsc::context_ptr& ctx, const gsc::expr_add_array_ptr& expr); + void emit_expr_size(const gsc::context_ptr& ctx, const gsc::expr_size_ptr& expr); + void emit_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr, bool set); + void emit_array_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr, bool set); + void emit_field_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr, bool set); + void emit_local_variable_ref(const gsc::context_ptr& ctx, const gsc::name_ptr& expr, bool set); + void emit_variable(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr); + void emit_array_variable(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr); + void emit_field_variable(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr); + void emit_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr); + void emit_clear_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr); + void emit_create_local_vars(const gsc::context_ptr& ctx); + void emit_remove_local_vars(const gsc::context_ptr& ctx); + void emit_object(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr); + void emit_animtree(const gsc::context_ptr& ctx, const gsc::animtree_ptr& animtree); + void emit_animation(const gsc::context_ptr& ctx, const gsc::animation_ptr& animation); + void emit_istring(const gsc::context_ptr& ctx, const gsc::istring_ptr& str); + void emit_string(const gsc::context_ptr& ctx, const gsc::string_ptr& str); + void emit_color(const gsc::context_ptr& ctx, const gsc::color_ptr& color); + void emit_vector(const gsc::context_ptr& ctx, const gsc::vector_ptr& vec); + void emit_float(const gsc::context_ptr& ctx, const gsc::float_ptr& num); + void emit_integer(const gsc::context_ptr& ctx, const gsc::integer_ptr& num); + void emit_false(const gsc::context_ptr& ctx, const gsc::false_ptr& expr); + void emit_true(const gsc::context_ptr& ctx, const gsc::true_ptr& expr); + void emit_opcode(const gsc::context_ptr& ctx, opcode op); + void emit_opcode(const gsc::context_ptr& ctx, opcode op, const std::string& data); + void emit_opcode(const gsc::context_ptr& ctx, opcode op, const std::vector& data); + void process_thread(const gsc::context_ptr& ctx, const gsc::thread_ptr& thread); + void process_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params); + void process_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt); + void process_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt); + void process_expr(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr); + void process_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt); + void process_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt); + void process_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt); + void process_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt); + void process_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt); + void process_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt); + void process_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt); + void process_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt); + void process_stmt_continue(const gsc::context_ptr& ctx, const gsc::stmt_continue_ptr& stmt); + void process_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt); + void register_variable(const gsc::context_ptr& ctx, const std::string& name); + void initialize_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& name); + void create_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& name); + auto variable_stack_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::uint8_t; + auto variable_create_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::string; + auto variable_access_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::string; + auto variable_initialized(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> bool; + auto is_include_call(const std::string& name, std::string& file) -> bool; + auto is_local_call(const std::string& name) -> bool; + auto is_builtin_call(const std::string& name) -> bool; + auto is_builtin_func(const std::string& name) -> bool; + auto is_builtin_method(const std::string& name) -> bool; + auto is_constant_condition(const gsc::expr_ptr& expr) -> bool; + auto create_label() -> std::string; + auto insert_label() -> std::string; + void insert_label(const std::string& label); + + auto map_known_includes(const std::string& include) -> bool; +}; + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/decompiler.cpp b/src/s4/xsk/decompiler.cpp new file mode 100644 index 00000000..5a041529 --- /dev/null +++ b/src/s4/xsk/decompiler.cpp @@ -0,0 +1,3386 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#include "stdafx.hpp" +#include "s4.hpp" + +namespace xsk::gsc::s4 +{ + +auto decompiler::output() -> std::vector +{ + std::vector output; + + auto data = std::make_unique(0x100000); + data->write_string("// S4 PC GSC\n// Decompiled by https://github.com/xensik/gsc-tool\n"); + data->write_string(program_->print()); + + output.resize(data->pos()); + std::memcpy(output.data(), data->buffer().data(), output.size()); + + return output; +} + +void decompiler::decompile(const std::string& file, std::vector& functions) +{ + filename_ = file; + program_ = std::make_unique(); + + for (auto& func : functions) + { + auto name = std::make_unique(func->name.substr(4)); + auto params = std::make_unique(); + auto block = std::make_unique(); + func_ = std::make_unique(std::move(name),std::move(params),std::move(block)); + + labels_ = func->labels; + expr_labels_.clear(); + stack_ = std::stack(); + + this->decompile_function(func); + + this->process_stack(func_); + + program_->definitions.push_back(gsc::define_ptr(std::move(func_))); + } +} + +void decompiler::decompile_function(const gsc::function_ptr& func) +{ + this->decompile_statements(func); + + if(stack_.size() > 0) + { + throw gsc::decomp_error("stack not emty at function end"); + } + + auto& block = func_->block; + + gsc::context ctx; + ctx.loc_end = utils::string::va("loc_%X", block->stmts.back().as_node->loc.begin.line); + + // remove last return + block->stmts.pop_back(); + + // hotfix empty else block at func end + if(block->stmts.size() > 0 && block->stmts.back().as_node->type == gsc::node_t::asm_jump) + { + if(block->stmts.back().as_jump->value == ctx.loc_end) + block->stmts.pop_back(); + } + + blocks_.push_back(ctx); + this->decompile_block(block); + blocks_.pop_back(); +} + +void decompiler::decompile_statements(const gsc::function_ptr& func) +{ + std::uint32_t last_null_loc = 0; + bool in_waittill = false; + + for (auto& inst : func->instructions) + { + auto loc = gsc::location(&filename_, inst->index); + + const auto itr = func->labels.find(inst->index); + + if (itr != func->labels.end()) + { + for(auto& entry : expr_labels_) + { + if(entry == itr->second) + { + decompile_expr(); + } + } + + for(auto& entry : tern_labels_) + { + if(entry == itr->second) + { + decompile_ternary(); + } + } + } + + switch (opcode(inst->opcode)) + { + case opcode::OP_End: + { + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::make_unique())); + func_->block->stmts.push_back(std::move(stmt)); + } + break; + case opcode::OP_Return: + { + auto expr = std::move(stack_.top()); + stack_.pop(); + auto stmt = gsc::stmt_ptr(std::make_unique(expr->loc, std::move(expr))); + func_->block->stmts.push_back(std::move(stmt)); + } + break; + case opcode::OP_GetZero: + { + auto node = std::make_unique(loc, "0"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetByte: + case opcode::OP_GetUnsignedShort: + case opcode::OP_GetInteger: + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetNegByte: + case opcode::OP_GetNegUnsignedShort: + { + auto node = std::make_unique(loc, "-" + inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetFloat: + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetVector: + { + auto x = gsc::expr_ptr(std::make_unique(loc, inst->data[0])); + auto y = gsc::expr_ptr(std::make_unique(loc, inst->data[1])); + auto z = gsc::expr_ptr(std::make_unique(loc, inst->data[2])); + auto node = std::make_unique(loc, std::move(x), std::move(y), std::move(z)); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetString: + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetIString: + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetUndefined: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EmptyArray: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetLevel: + case opcode::OP_GetLevelObject: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetAnim: + case opcode::OP_GetAnimObject: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetSelf: + case opcode::OP_GetSelfObject: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetGame: + case opcode::OP_GetGameRef: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetAnimation: + { + auto tree = utils::string::unquote(inst->data[0]); + + if(tree != "") + { + auto treename = std::make_unique(loc, inst->data[0]); + auto animtree = std::make_unique(loc, std::move(treename)); + program_->definitions.push_back(gsc::define_ptr(std::move(animtree))); + } + + auto node = std::make_unique(loc, utils::string::unquote(inst->data[1])); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetAnimTree: + { + auto tree = utils::string::unquote(inst->data[0]); + + if(tree != "") + { + auto treename = std::make_unique(loc, inst->data[0]); + auto animtree = std::make_unique(loc, std::move(treename)); + program_->definitions.push_back(gsc::define_ptr(std::move(animtree))); + } + + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetThisthread: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_GetBuiltinFunction: + case opcode::OP_GetBuiltinMethod: + { + auto file = std::make_unique(loc); + auto func = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(file), std::move(func)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_GetLocalFunction: + { + auto file = std::make_unique(loc); + auto func = std::make_unique(loc, inst->data[0].substr(4)); + auto stmt = std::make_unique(loc, std::move(file), std::move(func)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_GetFarFunction: + { + auto file = std::make_unique(loc, utils::string::backslash(inst->data[0])); + auto func = std::make_unique(loc, inst->data[1]); + auto stmt = std::make_unique(loc, std::move(file), std::move(func)); + stack_.push(std::move(stmt)); + }; + break; + case opcode::OP_CreateLocalVariable: + { + if(in_waittill) + { + auto expr = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(expr)); + } + else + { + auto stmt = std::make_unique(loc, inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + } + break; + case opcode::OP_RemoveLocalVariables: + { + auto stmt = std::make_unique(loc, inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_EvalLocalVariableCached0: + { + auto node = std::make_unique(loc, "0"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalVariableCached1: + { + auto node = std::make_unique(loc, "1"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalVariableCached2: + { + auto node = std::make_unique(loc, "2"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalVariableCached3: + { + auto node = std::make_unique(loc, "3"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalVariableCached4: + { + auto node = std::make_unique(loc, "4"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalVariableCached5: + { + auto node = std::make_unique(loc, "5"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalVariableCached: + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalArrayCached: + { + auto key = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto obj = gsc::expr_ptr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.as_node->loc, std::move(obj), std::move(key)); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalArray: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto key = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto node = std::make_unique(key.as_node->loc, std::move(obj), std::move(key)); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalNewLocalArrayRefCached0: + { + auto key = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto obj = gsc::expr_ptr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.as_node->loc, std::move(obj), std::move(key)); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalArrayRefCached0: + { + auto key = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto obj = gsc::expr_ptr(std::make_unique(loc, "0")); + auto node = std::make_unique(key.as_node->loc, std::move(obj), std::move(key)); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalArrayRefCached: + { + auto key = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto obj = gsc::expr_ptr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.as_node->loc, std::move(obj), std::move(key)); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalArrayRef: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto key = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto node = std::make_unique(key.as_node->loc, std::move(obj), std::move(key)); + stack_.push(std::move(node)); + } + break; + case opcode::OP_ClearArray: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto key = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = key.as_node->loc; + auto lvalue = gsc::expr_ptr(std::make_unique(loc, std::move(obj), std::move(key))); + auto rvalue = gsc::expr_ptr(std::make_unique(loc)); + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(expr))); + func_->block->stmts.push_back(std::move(stmt)); + } + break; + case opcode::OP_AddArray: + { + auto var = std::move(stack_.top()); + stack_.pop(); + auto array = std::move(stack_.top()); + stack_.pop(); + + if (array->type == gsc::node_t::data_empty_array) + { + auto args = std::make_unique(loc); + args->list.push_back(std::move(var)); + auto expr = std::make_unique(array->loc, std::move(args)); + stack_.push(std::move(expr)); + } + else if (array->type == gsc::node_t::expr_add_array) + { + (*(gsc::expr_add_array_ptr*)&array)->args->list.push_back(std::move(var)); + stack_.push(std::move(array)); + } + else + { + throw gsc::decomp_error("unknown add array type (could be an array variable name?)"); + } + } + break; + case opcode::OP_PreScriptCall: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_ScriptLocalFunctionCall2: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0].substr(4)); + auto file = std::make_unique(loc); + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptLocalFunctionCall: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0].substr(4)); + auto file = std::make_unique(loc); + + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + while(var->type != gsc::node_t::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptLocalMethodCall: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0].substr(4)); + auto file = std::make_unique(loc); + + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + while(var->type != gsc::node_t::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptLocalThreadCall: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0].substr(4)); + auto file = std::make_unique(loc); + + auto argnum = std::stoul(inst->data[1]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, true, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptLocalChildThreadCall: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0].substr(4)); + auto file = std::make_unique(loc); + + auto argnum = std::stoul(inst->data[1]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, true, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptLocalMethodThreadCall: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0].substr(4)); + auto file = std::make_unique(loc); + + auto argnum = std::stoul(inst->data[1]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, true, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptLocalMethodChildThreadCall: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0].substr(4)); + auto file = std::make_unique(loc); + + auto argnum = std::stoul(inst->data[1]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, true, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFarFunctionCall2: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[1]); + auto file = std::make_unique(loc, utils::string::backslash(inst->data[0])); + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFarFunctionCall: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[1]); + auto file = std::make_unique(loc, utils::string::backslash(inst->data[0])); + + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + while(var->type != gsc::node_t::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFarMethodCall: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[1]); + auto file = std::make_unique(loc, utils::string::backslash(inst->data[0])); + + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + while(var->type != gsc::node_t::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFarThreadCall: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[2]); + auto file = std::make_unique(loc, utils::string::backslash(inst->data[1])); + + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, true, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFarChildThreadCall: + { + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[2]); + auto file = std::make_unique(loc, utils::string::backslash(inst->data[1])); + + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, true, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFarMethodThreadCall: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[2]); + auto file = std::make_unique(loc, utils::string::backslash(inst->data[1])); + + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, true, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFarMethodChildThreadCall: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[2]); + auto file = std::make_unique(loc, utils::string::backslash(inst->data[1])); + + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, true, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptFunctionCallPointer: + { + auto args = std::make_unique(loc); + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = exprf.as_node->loc; + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + while(var->type != gsc::node_t::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, false, std::move(exprf), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptMethodCallPointer: + { + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + while(var->type != gsc::node_t::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, false, std::move(exprf), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptThreadCallPointer: + { + auto args = std::make_unique(loc); + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = exprf.as_node->loc; + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, false, std::move(exprf), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, true, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptChildThreadCallPointer: + { + auto args = std::make_unique(loc); + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = exprf.as_node->loc; + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, false, std::move(exprf), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, true, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptMethodThreadCallPointer: + { + auto args = std::make_unique(loc); + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, false, std::move(exprf), std::move(args))); + auto expr = std::make_unique(loc, true, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_ScriptMethodChildThreadCallPointer: + { + auto args = std::make_unique(loc); + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, false, std::move(exprf), std::move(args))); + auto expr = std::make_unique(loc, false, true, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinPointer: + { + auto args = std::make_unique(loc); + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = exprf.as_node->loc; + + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto obj = gsc::expr_ptr(std::make_unique()); + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, true, std::move(exprf), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethodPointer: + { + auto args = std::make_unique(loc); + auto exprf = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, true, std::move(exprf), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltin0: + { + auto obj = gsc::expr_ptr(std::make_unique()); + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltin1: + { + auto obj = gsc::expr_ptr(std::make_unique()); + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 1; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltin2: + { + auto obj = gsc::expr_ptr(std::make_unique()); + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 2; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltin3: + { + auto obj = gsc::expr_ptr(std::make_unique()); + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 3; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltin4: + { + auto obj = gsc::expr_ptr(std::make_unique()); + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 4; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltin5: + { + auto obj = gsc::expr_ptr(std::make_unique()); + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 5; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltin: + { + auto obj = gsc::expr_ptr(std::make_unique()); + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[1]); + auto file = std::make_unique(loc); + + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethod0: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethod1: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 1; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethod2: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 2; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethod3: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 3; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethod4: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 4; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethod5: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto file = std::make_unique(loc); + + for (size_t i = 5; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_CallBuiltinMethod: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto args = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[1]); + auto file = std::make_unique(loc); + + auto argnum = std::stoul(inst->data[0]); + + for (size_t i = argnum; i > 0; i--) + { + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + args->list.push_back(std::move(var)); + } + + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_DecTop: + { + auto expr = std::move(stack_.top()); + stack_.pop(); + loc = expr->loc; + auto stmt = std::make_unique(loc, std::move(*(gsc::expr_call_ptr*)&expr)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_inc: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_dec: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_bit_or: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_bit_ex_or: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_bit_and: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_equality: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_inequality: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_less: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_greater: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_less_equal: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_greater_equal: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_shift_left: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_shift_right: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_plus: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_minus: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_multiply: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_divide: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_mod: + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_wait: + { + auto expr = std::move(stack_.top()); + stack_.pop(); + loc = expr->loc; + auto stmt = std::make_unique(loc, std::move(expr)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_waittillFrameEnd: + { + auto stmt = gsc::stmt_ptr(std::make_unique(loc)); + func_->block->stmts.push_back(std::move(stmt)); + } + break; + case opcode::OP_waitframe: + { + auto stmt = gsc::stmt_ptr(std::make_unique(loc)); + func_->block->stmts.push_back(std::move(stmt)); + } + break; + case opcode::OP_waittill: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto nstr = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = nstr.as_node->loc; + auto args = std::make_unique(loc); + auto stmt = std::make_unique(loc, std::move(obj) , std::move(nstr), std::move(args)); + stack_.push(std::move(stmt)); + in_waittill = true; + } + break; + case opcode::OP_waittillmatch: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto expr = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = expr.as_node->loc; + + gsc::expr_arguments_ptr args = std::make_unique(); + args->loc = loc; + + while(stack_.size() > 0) + { + auto node = std::move(stack_.top()); + stack_.pop(); + args->loc = node->loc; + args->list.push_back(std::move(node)); + + } + loc = args->loc; + + auto stmt = std::make_unique(loc, std::move(obj), std::move(expr), std::move(args)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_clearparams: + { + auto args = std::make_unique(loc); + auto var = std::move(stack_.top()); + stack_.pop(); + + while(var->type != gsc::node_t::stmt_waittill && var->type != gsc::node_t::stmt_waittillmatch) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + } + + if(var->type == gsc::node_t::stmt_waittill) + { + std::reverse(args->list.begin(), args->list.end()); + (*(gsc::stmt_waittill_ptr*)&var)->args = std::move(args); + in_waittill = false; + } + + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(var))); + } + break; + case opcode::OP_checkclearparams: + break; + case opcode::OP_notify: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto nstr = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + + auto args = std::make_unique(loc); + + auto var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + while(var->type != gsc::node_t::asm_voidcodepos) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); + stack_.pop(); + loc = var->loc; + } + + auto stmt = std::make_unique(loc, std::move(obj) , std::move(nstr), std::move(args)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_endon: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto nstr = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = nstr.as_node->loc; + auto stmt = std::make_unique(loc, std::move(obj) , std::move(nstr)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_voidCodepos: + { + auto node = std::make_unique(loc); + stack_.push(std::move(node)); + } + break; + case opcode::OP_vector: + { + auto x = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto y = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + auto z = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = z.as_node->loc; + auto expr = std::make_unique(loc, std::move(x), std::move(y), std::move(z)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_size: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_EvalLevelFieldVariable: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_EvalAnimFieldVariable: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_EvalSelfFieldVariable: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_EvalFieldVariable: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_EvalLevelFieldVariableRef: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_EvalAnimFieldVariableRef: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_EvalSelfFieldVariableRef: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_EvalFieldVariableRef: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto field = std::make_unique(loc, inst->data[0]); + auto stmt = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(stmt)); + } + break; + case opcode::OP_ClearFieldVariable: + { + auto obj = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = obj.as_node->loc; + auto field = std::make_unique(loc, inst->data[0]); + auto expr = gsc::expr_ptr(std::make_unique(loc, std::move(obj), std::move(field))); + auto undef = gsc::expr_ptr(std::make_unique(loc)); + auto e = std::make_unique(loc, std::move(expr), std::move(undef)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::make_unique(loc, std::move(e)))); + } + break; + case opcode::OP_SafeCreateVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; + case opcode::OP_SafeSetWaittillVariableFieldCached: + { + if(stack_.top()->type != gsc::node_t::asm_create) + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + } + break; + case opcode::OP_EvalLocalVariableRefCached0: + { + auto node = std::make_unique(loc, "0"); + stack_.push(std::move(node)); + } + break; + case opcode::OP_EvalLocalVariableRefCached: + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_SetLevelFieldVariableField: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = gsc::expr_ptr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = rvalue.as_node->loc; + auto e = std::make_unique(loc,std::move(lvalue), std::move(rvalue)); + auto stmt = std::make_unique(loc, std::move(e)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_SetVariableField: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + + if(lvalue.as_node->type == gsc::node_t::expr_increment) + { + auto stmt = std::make_unique(loc, std::move(lvalue.as_increment)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + else if(lvalue.as_node->type == gsc::node_t::expr_decrement) + { + auto stmt = std::make_unique(loc, std::move(lvalue.as_decrement)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + else + { + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = rvalue.as_node->loc; + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + auto stmt = std::make_unique(loc, std::move(e)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + } + break; + case opcode::OP_SetAnimFieldVariableField: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = gsc::expr_ptr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = rvalue.as_node->loc; + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + auto stmt = std::make_unique(loc, std::move(e)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_SetSelfFieldVariableField: + { + auto obj = gsc::expr_ptr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = gsc::expr_ptr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = rvalue.as_node->loc; + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + auto stmt = std::make_unique(loc, std::move(e)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_SetLocalVariableFieldCached0: + { + auto lvalue = gsc::expr_ptr(std::make_unique(loc, "0")); + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = rvalue.as_node->loc; + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + auto stmt = std::make_unique(loc, std::move(e)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_SetNewLocalVariableFieldCached0: + { + auto lvalue = gsc::expr_ptr(std::make_unique(loc, inst->data[0])); + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = rvalue.as_node->loc; + + if(func_->block->stmts.size() > 0) + { + std::vector creates; + + while(func_->block->stmts.back().as_node->type == gsc::node_t::asm_create) + { + auto& entry = func_->block->stmts.back(); + if(loc.begin.line < entry.as_node->loc.begin.line) + { + creates.push_back(entry.as_asm_create->index); + func_->block->stmts.pop_back(); + continue; + } + break; + } + + std::reverse(creates.begin(), creates.end()); + lvalue.as_asm_create->vars = creates; + } + + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + auto stmt = std::make_unique(loc, std::move(e)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_SetLocalVariableFieldCached: + { + auto lvalue = gsc::expr_ptr(std::make_unique(loc, inst->data[0])); + auto rvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = rvalue.as_node->loc; + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + auto stmt = std::make_unique(loc, std::move(e)); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_ClearLocalVariableFieldCached: + { + auto stmt = std::make_unique(loc, inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_ClearLocalVariableFieldCached0: + { + auto stmt = std::make_unique(loc,"0"); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(stmt))); + } + break; + case opcode::OP_EvalLocalVariableObjectCached: + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + case opcode::OP_CastFieldObject: + case opcode::OP_CastBool: + break; + case opcode::OP_BoolNot: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_BoolComplement: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_switch: + { + auto expr = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = expr.as_node->loc; + auto sw = std::make_unique(loc, std::move(expr), inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(sw))); + } + break; + case opcode::OP_endswitch: + { + auto count = inst->data[0]; + inst->data.erase(inst->data.begin()); + auto data = inst->data; + auto end = std::make_unique(loc, data, count); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(end))); + } + break; + case opcode::OP_jump: + { + auto expr = std::make_unique(loc, inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(expr))); + if(stack_.size() != 0) tern_labels_.push_back(inst->data[0]); + + } + break; + case opcode::OP_jumpback: + { + auto expr = std::make_unique(loc, inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(expr))); + } + break; + case opcode::OP_JumpOnTrue: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto e_not = gsc::expr_ptr(std::make_unique(loc, std::move(lvalue))); + auto expr = std::make_unique(loc, std::move(e_not), inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(expr))); + } + break; + case opcode::OP_JumpOnFalse: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), inst->data[0]); + func_->block->stmts.push_back(gsc::stmt_ptr(std::move(expr))); + } + break; + case opcode::OP_JumpOnTrueExpr: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), inst->data[0]); + stack_.push(std::move(expr)); + expr_labels_.push_back(inst->data[0]); + } + break; + case opcode::OP_JumpOnFalseExpr: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue), inst->data[0]); + stack_.push(std::move(expr)); + expr_labels_.push_back(inst->data[0]); + } + break; + case opcode::OP_FormalParams: + { + auto count = std::stoi(inst->data[0]); + for(auto i = 1; i <= count; i++) + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[i])); + } + } + break; + case opcode::OP_IsDefined: + { + auto param = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = param.as_node->loc; + auto args = std::make_unique(loc); + args->list.push_back(std::move(param)); + auto name = std::make_unique(loc, "isdefined"); + auto file = std::make_unique(loc); + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_IsTrue: + { + auto param = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = param.as_node->loc; + auto args = std::make_unique(loc); + args->list.push_back(std::move(param)); + auto name = std::make_unique(loc, "istrue"); + auto file = std::make_unique(loc); + auto func = gsc::expr_call_type_ptr(std::make_unique(loc, std::move(file), std::move(name), std::move(args))); + auto obj = gsc::expr_ptr(std::make_unique()); + auto expr = std::make_unique(loc, false, false, std::move(obj) ,std::move(func)); + stack_.push(std::move(expr)); + } + break; + case opcode::OP_BoolNotAfterAnd: + { + auto lvalue = gsc::expr_ptr(std::move(stack_.top())); + stack_.pop(); + loc = lvalue.as_node->loc; + auto expr = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(expr)); + } + break; + default: + throw gsc::decomp_error("unhandled opcode " + resolver::opcode_name(inst->opcode)); + break; + } + } +} + +void decompiler::decompile_expr() +{ + auto expr = std::move(stack_.top()); + stack_.pop(); + + auto jump_expr = std::move(stack_.top()); + stack_.pop(); + auto loc = jump_expr->loc; + + if(jump_expr->type == gsc::node_t::asm_jump_true_expr) + { + auto lvalue = std::move((*(gsc::asm_jump_true_expr_ptr*)&jump_expr)->expr); + auto rvalue = gsc::expr_ptr(std::move(expr)); + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(e)); + } + else if(jump_expr->type == gsc::node_t::asm_jump_false_expr) + { + auto lvalue = std::move((*(gsc::asm_jump_false_expr_ptr*)&jump_expr)->expr); + auto rvalue = gsc::expr_ptr(std::move(expr)); + auto e = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(e)); + } + else + { + throw gsc::decomp_error("TRIED TO DECOMPILE INVALID JUMP EXPR!"); + } +} + +void decompiler::decompile_ternary() +{ + auto rvalue = std::move(stack_.top()); + stack_.pop(); + auto lvalue = std::move(stack_.top()); + stack_.pop(); + + func_->block->stmts.pop_back(); + auto stmt = std::move(func_->block->stmts.back()); + func_->block->stmts.pop_back(); + + if(stmt.as_node->type == node_t::asm_jump_cond) + { + auto loc = stmt.as_cond->loc; + auto e = std::make_unique(loc, std::move(stmt.as_cond->expr), std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(e)); + } + else + { + throw gsc::decomp_error("TRIED TO DECOMPILE INVALID TERNARY EXPR!"); + } +} + +void decompiler::decompile_block(const gsc::stmt_list_ptr& block) +{ + this->decompile_search_infinite(block); + this->decompile_search_loop(block); + this->decompile_search_switch(block); + this->decompile_search_ifelse(block); + this->decompile_break_continue(block); +} + +void decompiler::decompile_search_infinite(const gsc::stmt_list_ptr& block) +{ + std::int32_t index = block->stmts.size() - 1; + + while(index >= 0) + { + if(block->stmts.at(index).as_node->type == gsc::node_t::asm_jump_back) + { + auto break_loc = last_location_index(block, index) ? blocks_.back().loc_end : utils::string::va("loc_%X", block->stmts.at(index+1).as_node->loc.begin.line); + auto begin_loc = block->stmts.at(index).as_jump_back->value; + auto start = find_location_index(block, begin_loc); + + if(block->stmts.at(start).as_node->type != gsc::node_t::asm_jump_cond) + { + decompile_infinite(block, start, index); + index = start; + } + else if (block->stmts.at(start).as_cond->value != break_loc) + { + decompile_infinite(block, start, index); + index = start; + } + } + + index--; + } +} + +void decompiler::decompile_search_loop(const gsc::stmt_list_ptr& block) +{ + auto index = 0; + + while(index < block->stmts.size()) + { + auto& stmt = block->stmts.at(index); + + if(stmt.as_node->type == gsc::node_t::asm_jump_cond) + { + std::uint32_t end; + if(stmt.as_cond->value == blocks_.back().loc_end) + { + end = block->stmts.size() - 1; + } + else + { + end = find_location_index(block, stmt.as_cond->value) - 1; + } + + if(block->stmts.at(end).as_node->type == gsc::node_t::asm_jump_back + && utils::string::va("loc_%X", block->stmts.at(index).as_node->loc.begin.line) == block->stmts.at(end).as_jump_back->value) + { + decompile_loop(block, index, end); + index = 0; + } + } + index++; + } +} + +void decompiler::decompile_search_switch(const gsc::stmt_list_ptr& block) +{ + auto index = 0; + + while(index < block->stmts.size()) + { + if(block->stmts.at(index).as_node->type == gsc::node_t::asm_switch) + { + decompile_switch(block, index); + } + + index++; + } +} + +void decompiler::decompile_search_ifelse(const gsc::stmt_list_ptr& block) +{ + auto index = 0; + + while(index < block->stmts.size()) + { + auto& stmt = block->stmts.at(index); + + if(stmt.as_node->type == gsc::node_t::asm_jump_cond) + { + std::uint32_t end; + if(stmt.as_cond->value == blocks_.back().loc_end) + { + end = block->stmts.size() - 1; + } + else + { + end = find_location_index(block, stmt.as_cond->value) - 1; + } + + auto last_loc = blocks_.back().loc_end; + + if(block->stmts.at(end).as_node->type == gsc::node_t::asm_jump) + { + // if block is a loop check break, continue + if(block->stmts.at(end).as_jump->value == blocks_.back().loc_continue) + { + // last if/else inside a loop still trigger this :( + decompile_if(block, index, end); + } + else if(block->stmts.at(end).as_jump->value == blocks_.back().loc_break) + { + decompile_if(block, index, end); + } + else if(block->stmts.at(end).as_jump->value == blocks_.back().loc_end) + { + decompile_ifelse(block, index, end); + } + else if(block->stmts.at(end).as_jump->value == stmt.as_cond->value) + { + decompile_if(block, index, end); // if block, have a last empty else inside + } + else + { + decompile_ifelse(block, index, end); // TODO: if else block is empty, convert it to only if! + } + } + else if(block->stmts.at(end).as_node->type == gsc::node_t::stmt_return + && block->stmts.at(end).as_return->expr.as_node->type == gsc::node_t::null) + { + if(blocks_.back().loc_break != "" || blocks_.back().loc_continue != "") + { + decompile_if(block, index, end); // inside a loop cant be last + } + else if(end - index == 1) + { + decompile_if(block, index, end); // only one explicit return + } + else if(block->stmts.back().as_node->type != gsc::node_t::stmt_return) + { + decompile_if(block, index, end); // block end is not a last return + } + else if(blocks_.back().is_last && block->stmts.back().as_node->type != gsc::node_t::stmt_return) + { + decompile_if(block, index, end); // inside a last block but is not and inner last + } + else if(find_location_reference(block, end, block->stmts.size(), last_loc)) + { + decompile_if(block, index, end); // reference to func end after the if + } + else if(blocks_.size() > 1 && !blocks_.back().is_last) + { + decompile_if(block, index, end); // fake last ifelse + } + else + { + decompile_last_ifelse(block, index, end); // special case + } + } + else + { + decompile_if(block, index, end); + } + } + index++; + } +} + +void decompiler::decompile_break_continue(const gsc::stmt_list_ptr& block) +{ + auto index = 0; + + while(index < block->stmts.size()) + { + if(block->stmts.at(index).as_node->type == gsc::node_t::asm_jump) + { + auto loc = block->stmts.at(index).as_node->loc; + auto jump_loc = block->stmts.at(index).as_jump->value; + + if(jump_loc == blocks_.back().loc_continue) + { + block->stmts.erase(block->stmts.begin() + index); + auto stmt = gsc::stmt_ptr(std::make_unique(loc)); + block->stmts.insert(block->stmts.begin() + index, std::move(stmt)); + } + else if(jump_loc == blocks_.back().loc_break) + { + block->stmts.erase(block->stmts.begin() + index); + auto stmt = gsc::stmt_ptr(std::make_unique(loc)); + block->stmts.insert(block->stmts.begin() + index, std::move(stmt)); + } + } + + index++; + } +} + +void decompiler::decompile_if(const gsc::stmt_list_ptr& block, std::uint32_t begin, std::uint32_t end) +{ + gsc::context ctx; + ctx.loc_end = block->stmts.at(begin).as_cond->value; + ctx.loc_break = blocks_.back().loc_break; + ctx.loc_continue = blocks_.back().loc_continue; + + auto loc = block->stmts.at(begin).as_node->loc; + auto expr = std::move(block->stmts.at(begin).as_cond->expr); + + block->stmts.erase(block->stmts.begin() + begin); // remove condition + + auto if_block = std::make_unique(loc); + + for(auto i = begin; i < end; i++) + { + if_block->stmts.push_back(std::move(block->stmts[begin])); + block->stmts.erase(block->stmts.begin() + begin); + } + + blocks_.push_back(ctx); + decompile_block(if_block); + blocks_.pop_back(); + + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(expr), gsc::stmt_ptr(std::move(if_block)))); + block->stmts.insert(block->stmts.begin() + begin, std::move(stmt)); +} + +void decompiler::decompile_ifelse(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end) +{ + gsc::context ctx; + ctx.loc_end = utils::string::va("loc_%X", block->stmts.at(end).as_node->loc.begin.line); + ctx.loc_break = blocks_.back().loc_break; + ctx.loc_continue = blocks_.back().loc_continue; + + auto loc = block->stmts.at(start).as_node->loc; + auto expr = std::move(block->stmts.at(start).as_cond->expr); + + block->stmts.erase(block->stmts.begin() + start); // remove condition + end = end - 1; + + auto if_block = std::make_unique(loc); + + for(auto i = start; i < end; i++) // skip the jump + { + if_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + blocks_.push_back(ctx); + decompile_block(if_block); + blocks_.pop_back(); + + auto end_loc = block->stmts.at(start).as_jump->value; + + block->stmts.erase(block->stmts.begin() + start); // remove jump + + std::uint32_t end_index; + + if(end_loc == blocks_.back().loc_end) + { + end_index = block->stmts.size(); + } + else + { + end_index = find_location_index(block, end_loc); + } + + gsc::context ctx2; + ctx2.loc_end = end_loc; + ctx2.loc_break = blocks_.back().loc_break; + ctx2.loc_continue = blocks_.back().loc_continue; + + auto else_block = std::make_unique(loc); + + for(auto i = start; i < end_index; i++) + { + else_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + blocks_.push_back(ctx2); + decompile_block(else_block); + blocks_.pop_back(); + + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(expr), gsc::stmt_ptr(std::move(if_block)), gsc::stmt_ptr(std::move(else_block)))); + block->stmts.insert(block->stmts.begin() + start, std::move(stmt)); +} + +void decompiler::decompile_last_ifelse(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end) +{ + gsc::context ctx; + ctx.is_last = true; + + auto inner_end = find_location_index(block, block->stmts.at(start).as_cond->value) - 1; + ctx.loc_end = utils::string::va("loc_%X",block->stmts.at(inner_end).as_node->loc.begin.line); + auto loc = block->stmts.at(start).as_node->loc; + auto expr = std::move(block->stmts.at(start).as_cond->expr); + + block->stmts.erase(block->stmts.begin() + start); // remove condition + end = end - 1; + + auto if_block = std::make_unique(loc); + + for(auto i = start; i < end; i++) + { + if_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + block->stmts.erase(block->stmts.begin() + start); // remove if block return; + + blocks_.push_back(ctx); + decompile_block(if_block); + blocks_.pop_back(); + + if(start == block->stmts.size()) + { + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(expr), gsc::stmt_ptr(std::move(if_block)))); + block->stmts.insert(block->stmts.begin() + start, std::move(stmt)); + } + else + { + gsc::context ctx2; + ctx2.is_last = true; + + auto else_block = std::make_unique(loc); + + end = block->stmts.size(); + ctx2.loc_end = utils::string::va("loc_%X", block->stmts.at(end - 1).as_node->loc.begin.line); // return is the block end + + for(auto i = start; i < end; i++) + { + else_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + else_block->stmts.pop_back(); // remove else return; + + blocks_.push_back(ctx2); + decompile_block(else_block); + blocks_.pop_back(); + + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(expr), gsc::stmt_ptr(std::move(if_block)), gsc::stmt_ptr(std::move(else_block)))); + block->stmts.insert(block->stmts.begin() + start, std::move(stmt)); + } +} + +void decompiler::decompile_infinite(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end) +{ + gsc::context ctx; + ctx.loc_break = last_location_index(block, end) ? blocks_.back().loc_end : utils::string::va("loc_%X", block->stmts.at(end+1).as_node->loc.begin.line); + ctx.loc_end = utils::string::va("loc_%X", block->stmts.at(end).as_node->loc.begin.line); + ctx.loc_continue = utils::string::va("loc_%X", block->stmts.at(end).as_node->loc.begin.line); + + auto loc = block->stmts.at(start).as_node->loc; + + block->stmts.erase(block->stmts.begin() + end); // remove jump back + + auto for_block = std::make_unique(loc); + + for(auto i = start; i < end; i++) + { + for_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + blocks_.push_back(ctx); + decompile_block(for_block); + blocks_.pop_back(); + + auto pre_expr = gsc::stmt_ptr(std::make_unique()); + auto expr = gsc::expr_ptr(std::make_unique()); + auto post_expr = gsc::stmt_ptr(std::make_unique()); + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(pre_expr), std::move(expr), std::move(post_expr), gsc::stmt_ptr(std::move(for_block)))); + block->stmts.insert(block->stmts.begin() + start, std::move(stmt)); +} + +void decompiler::decompile_loop(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end) +{ + auto& last_stmt = block->stmts.at(end-1); + if(last_stmt.as_node->type == gsc::node_t::stmt_assign) + { + if(last_stmt.as_assign->expr->type == gsc::node_t::expr_assign_equal) + { + auto& rval = last_stmt.as_assign->expr->rvalue; + if(rval.as_node->type == gsc::node_t::expr_call) + { + if(rval.as_call->func.as_node->type == gsc::node_t::expr_call_function) + { + if(utils::string::to_lower(rval.as_call->func.as_func->name->value) == "getnextarraykey") + { + auto ref2 = utils::string::va("loc_%X", block->stmts.at(start).as_node->loc.begin.line); + if(find_location_reference(block, 0, start, ref2)) + { + // begin is at condition, not pre-expr + //decompile_while(block, start, end); + //return; + } + else + { + decompile_foreach(block, start, end); + return; + } + } + } + } + } + + if(start > 0) // while at func start + { + auto index = 1; + while(block->stmts.at(start - index).as_node->type == gsc::node_t::asm_create) + { + if(start - index > 0) + index++; + } + + if(block->stmts.at(start - index).as_node->type == gsc::node_t::stmt_assign) + { + auto ref = utils::string::va("loc_%X", block->stmts.at(end).as_node->loc.begin.line); + auto ref2 = utils::string::va("loc_%X", block->stmts.at(start).as_node->loc.begin.line); + + if(find_location_reference(block, start, end, ref)) + { + // continue is at jumpback, not post-expr + decompile_while(block, start, end); + return; + } + else if(find_location_reference(block, 0, start, ref2)) + { + // begin is at condition, not pre-expr + decompile_while(block, start, end); + return; + } + else + { + decompile_for(block, start, end); + return; + } + } + } + } + + decompile_while(block, start, end); +} + +void decompiler::decompile_while(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end) +{ + gsc::context ctx; + ctx.loc_break = block->stmts.at(start).as_cond->value; + ctx.loc_end = utils::string::va("loc_%X", block->stmts.at(end).as_node->loc.begin.line); + ctx.loc_continue = utils::string::va("loc_%X",block->stmts.at(end).as_node->loc.begin.line); + + auto loc = block->stmts.at(start).as_node->loc; + auto expr = std::move(block->stmts.at(start).as_cond->expr); + + block->stmts.erase(block->stmts.begin() + end); // remove jump back + block->stmts.erase(block->stmts.begin() + start); // remove condition + end = end - 1; + + auto while_block = std::make_unique(loc); + + for(auto i = start; i < end; i++) + { + while_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + blocks_.push_back(ctx); + decompile_block(while_block); + blocks_.pop_back(); + + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(expr), gsc::stmt_ptr(std::move(while_block)))); + block->stmts.insert(block->stmts.begin() + start, std::move(stmt)); +} + +void decompiler::decompile_for(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end) +{ + gsc::context ctx; + ctx.loc_break = block->stmts.at(start).as_cond->value; + ctx.loc_end = utils::string::va("loc_%X", block->stmts.at(end - 1).as_node->loc.begin.line); + ctx.loc_continue = utils::string::va("loc_%X", block->stmts.at(end - 1).as_node->loc.begin.line); + + // remove emit local var_creates + std::vector creates; + while(block->stmts.at(start - 1).as_node->type == gsc::node_t::asm_create) + { + creates.push_back(block->stmts.at(start - 1).as_asm_create->index); + block->stmts.erase(block->stmts.begin() + start - 1); + start--; + end--; + } + + std::reverse(creates.begin(), creates.end()); + + auto loc = block->stmts.at(start - 1).as_node->loc; + auto expr = std::move(block->stmts.at(start).as_cond->expr); + auto pre_expr = gsc::stmt_ptr(std::make_unique()); + pre_expr.as_list->stmts.push_back(std::move(block->stmts.at(start - 1))); + pre_expr.as_list->is_expr = true; + auto post_expr = gsc::stmt_ptr(std::make_unique()); + post_expr.as_list->stmts.push_back(std::move(block->stmts.at(end - 1))); + post_expr.as_list->is_expr = true; + + start = start - 1; + end = end - 2; + for(auto i = start; i < start + 2; i++) // remove prologue (pre-expr, condition) + { + block->stmts.erase(block->stmts.begin() + start); + } + + end = end - 1; // set end in post-expr + for(auto i = end; i < end + 2; i++) // remove epilogue (post-expr, jump back) + { + block->stmts.erase(block->stmts.begin() + end); + } + + auto for_block = std::make_unique(loc); + + for(auto i = start; i < end; i++) + { + for_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + blocks_.push_back(ctx); + decompile_block(for_block); + blocks_.pop_back(); + + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(pre_expr), std::move(expr), std::move(post_expr), gsc::stmt_ptr(std::move(for_block)))); + stmt.as_for->vars = creates; + block->stmts.insert(block->stmts.begin() + start, std::move(stmt)); +} + +void decompiler::decompile_foreach(const gsc::stmt_list_ptr& block, std::uint32_t begin, std::uint32_t end) +{ + gsc::context ctx; + ctx.loc_break = block->stmts.at(begin).as_cond->value; + ctx.loc_end = utils::string::va("loc_%X", block->stmts.at(end - 1).as_node->loc.begin.line); + ctx.loc_continue = utils::string::va("loc_%X", block->stmts.at(end - 1).as_node->loc.begin.line); + + // remove local var_creates + std::vector creates; + while(block->stmts.at(begin - 1).as_node->type == gsc::node_t::asm_create) + { + creates.push_back(block->stmts.at(begin - 1).as_asm_create->index); + block->stmts.erase(block->stmts.begin() + begin - 1); + begin--; + end--; + } + + std::reverse(creates.begin(), creates.end()); + + auto loc = block->stmts.at(begin - 2).as_node->loc; + + auto pre_expr = gsc::stmt_ptr(std::make_unique()); + pre_expr.as_list->stmts.push_back(std::move(block->stmts[begin-2])); + pre_expr.as_list->stmts.push_back(std::move(block->stmts[begin-1])); + auto stmt0 = std::move(block->stmts[begin+1]); + + begin = begin - 2; + end = end - 4; + for(auto i = begin; i < begin + 4; i++) // remove prologue ( array, elem, cond, elemRef) + { + block->stmts.erase(block->stmts.begin() + begin); + } + + end = end - 1; // set end to post-expr + + for(auto i = end; i < end + 2; i++) // remove epilogue ( post-expr, jump back) + { + block->stmts.erase(block->stmts.begin() + end); + } + + if(block->stmts.size() > end && block->stmts.at(end).as_node->type == gsc::node_t::asm_clear) + { + block->stmts.erase(block->stmts.begin() + end); + } + + auto use_key = true; + + if(block->stmts.size() > end && block->stmts.at(end).as_node->type == gsc::node_t::asm_clear) + { + block->stmts.erase(block->stmts.begin() + end); + use_key = false; + } + + auto foreach_block = std::make_unique(loc); + + for(auto i = begin; i < end; i++) + { + foreach_block->stmts.push_back(std::move(block->stmts[begin])); + block->stmts.erase(block->stmts.begin() + begin); + } + + blocks_.push_back(ctx); + decompile_block(foreach_block); + blocks_.pop_back(); + + auto foreach_stmt = gsc::stmt_ptr(std::make_unique(loc, gsc::stmt_ptr(std::move(foreach_block)), use_key)); + foreach_stmt.as_foreach->vars = creates; + foreach_stmt.as_foreach->pre_expr = std::move(pre_expr); + foreach_stmt.as_foreach->stmt0 = std::move(stmt0); + + block->stmts.insert(block->stmts.begin() + begin, std::move(foreach_stmt)); +} + +void decompiler::decompile_switch(const gsc::stmt_list_ptr& block, std::uint32_t start) +{ + gsc::context ctx; + ctx.loc_continue = blocks_.back().loc_continue; + ctx.loc_end = block->stmts.at(start).as_asm_switch->value; + + auto loc = block->stmts.at(start).as_node->loc; + auto expr = std::move(block->stmts.at(start).as_asm_switch->expr); + auto end_loc = block->stmts.at(start).as_asm_switch->value; + auto end = find_location_index(block, end_loc); + + if(end == block->stmts.size() - 1) + { + ctx.loc_break = blocks_.back().loc_end; + } + else + { + ctx.loc_break = utils::string::va("loc_%X", block->stmts.at(end + 1).as_node->loc.begin.line); + } + + // collect cases + auto casenum = std::atol(block->stmts.at(end).as_asm_endswitch->count.data()); + auto data = block->stmts.at(end).as_asm_endswitch->data; + auto idx = 0; + + for(auto i = 0; i < casenum; i++) + { + if(data.at(idx) == "case") + { + auto loc_str = data.at(idx+2); + auto loc_idx = find_location_index(block, loc_str); + auto loc_pos = gsc::location(&filename_, std::stol(loc_str.substr(4), 0, 16)); + auto value = gsc::expr_ptr(std::make_unique(loc_pos, data.at(idx+1))); + auto list = std::make_unique(loc); + list->is_case = true; + auto stmt = gsc::stmt_ptr(std::make_unique(loc_pos, std::move(value), std::move(list))); + block->stmts.insert(block->stmts.begin() + loc_idx, std::move(stmt)); + idx += 3; + } + else if(data.at(idx) == "default") + { + auto loc_str = data.at(idx+1); + auto loc_idx = find_location_index(block, loc_str); + auto loc_pos = gsc::location(&filename_, std::stol(loc_str.substr(4), 0, 16)); + auto list = std::make_unique(loc); + list->is_case = true; + auto stmt = gsc::stmt_ptr(std::make_unique(loc_pos, std::move(list))); + while(block->stmts.at(loc_idx).as_node->type == gsc::node_t::stmt_case) + loc_idx++; + block->stmts.insert(block->stmts.begin() + loc_idx, std::move(stmt)); + idx += 2; + } + } + + end = find_location_index(block, end_loc) - 1; // update end; + block->stmts.erase(block->stmts.begin() + start); // remove switch + block->stmts.erase(block->stmts.begin() + end); // remove endswitch + + //decompile block + auto sw_block = std::make_unique(loc); + + for(auto i = start; i < end; i++) + { + sw_block->stmts.push_back(std::move(block->stmts[start])); + block->stmts.erase(block->stmts.begin() + start); + } + + blocks_.push_back(ctx); + decompile_block(sw_block); + blocks_.pop_back(); + + auto stmt_list = std::make_unique(loc); + gsc::stmt_ptr current_case = gsc::stmt_ptr(std::make_unique()); + + auto num = sw_block->stmts.size(); + for(auto i = 0; i < num; i++) + { + auto& entry = sw_block->stmts[0]; + + if(entry.as_node->type == gsc::node_t::stmt_case || entry.as_node->type == gsc::node_t::stmt_default) + { + if(current_case.as_node->type != gsc::node_t::null) + { + stmt_list->stmts.push_back(std::move(current_case)); + } + + current_case = std::move(sw_block->stmts[0]); + sw_block->stmts.erase(sw_block->stmts.begin()); + } + else + { + if(current_case.as_node->type != gsc::node_t::null) + { + if(current_case.as_node->type == gsc::node_t::stmt_case) + { + current_case.as_case->stmt->stmts.push_back(std::move(sw_block->stmts[0])); + sw_block->stmts.erase(sw_block->stmts.begin()); + } + else + { + current_case.as_default->stmt->stmts.push_back(std::move(sw_block->stmts[0])); + sw_block->stmts.erase(sw_block->stmts.begin()); + } + } + else + { + gsc::decomp_error("missing case before stmt inside switch!"); + } + } + } + + if(current_case.as_node->type != gsc::node_t::null) + { + stmt_list->stmts.push_back(std::move(current_case)); + } + + auto stmt = gsc::stmt_ptr(std::make_unique(loc, std::move(expr), std::move(stmt_list))); + block->stmts.insert(block->stmts.begin() + start, std::move(stmt)); +} + +auto decompiler::find_location_reference(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end, const std::string& location) -> bool +{ + for(auto i = start; i < end; i++) + { + if(block->stmts.at(i).as_node->type == gsc::node_t::asm_jump_cond) + { + if(block->stmts.at(i).as_cond->value == location) + return true; + } + else if(block->stmts.at(i).as_node->type == gsc::node_t::asm_jump) + { + if(block->stmts.at(i).as_jump->value == location) + return true; + } + } + + return false; +} + +auto decompiler::find_location_index(const gsc::stmt_list_ptr& block, const std::string& location) -> std::uint32_t +{ + auto index = 0; + + if(location == blocks_.back().loc_end) + return block->stmts.size(); + + for(auto& stmt : block->stmts) + { + if(stmt.as_node->loc.begin.line == std::stol(location.substr(4), 0, 16)) + return index; + + index++; + } + + throw gsc::decomp_error("LOCATION NOT FOUND! (" + location + ")"); +} + +auto decompiler::last_location_index(const gsc::stmt_list_ptr& block, std::uint32_t index) -> bool +{ + if(index == block->stmts.size() - 1) + return true; + + return false; +} + +void decompiler::process_stack(const gsc::thread_ptr& thread) +{ + auto ctx = std::make_unique(); + + process_parameters(ctx, thread->params); + process_stmt_list(ctx, thread->block); + +} + +void decompiler::process_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params) +{ + for(const auto& param : params->list) + { + ctx->local_vars.push_back({ param->value, static_cast(std::stoi(param->value.substr(4))), true }); + ctx->local_vars_create_count++; + } +} + +void decompiler::process_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt) +{ + switch(stmt.as_node->type) + { + case gsc::node_t::stmt_list: process_stmt_list(ctx, stmt.as_list); break; + case gsc::node_t::stmt_call: process_stmt_call(ctx, stmt.as_call); break; + case gsc::node_t::stmt_assign: process_stmt_assign(ctx, stmt.as_assign); break; + case gsc::node_t::stmt_endon: process_stmt_endon(ctx, stmt.as_endon); break; + case gsc::node_t::stmt_notify: process_stmt_notify(ctx, stmt.as_notify); break; + case gsc::node_t::stmt_wait: process_stmt_wait(ctx, stmt.as_wait); break; + case gsc::node_t::stmt_waittill: process_stmt_waittill(ctx, stmt.as_waittill); break; + case gsc::node_t::stmt_waittillmatch: process_stmt_waittillmatch(ctx, stmt.as_waittillmatch); break; + case gsc::node_t::stmt_if: process_stmt_if(ctx, stmt.as_if); break; + case gsc::node_t::stmt_ifelse: process_stmt_ifelse(ctx, stmt.as_ifelse); break; + case gsc::node_t::stmt_while: process_stmt_while(ctx, stmt.as_while); break; + case gsc::node_t::stmt_for: process_stmt_for(ctx, stmt.as_for); break; + case gsc::node_t::stmt_foreach: process_stmt_foreach(ctx, stmt.as_foreach); break; + case gsc::node_t::stmt_switch: process_stmt_switch(ctx, stmt.as_switch); break; + case gsc::node_t::stmt_break: process_stmt_break(ctx, stmt.as_break); break; + case gsc::node_t::stmt_return: process_stmt_return(ctx, stmt.as_return); break; + case gsc::node_t::asm_remove: process_var_remove(ctx, stmt.as_asm_remove); break; + case gsc::node_t::asm_create: + { + auto expr = gsc::expr_ptr(std::make_unique(stmt.as_asm_create->index)); + process_var_create(ctx, expr, true); + } + break; + default: break; + } +} + +void decompiler::process_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt) +{ + for (const auto& entry : stmt->stmts) + { + process_stmt(ctx, entry); + } + + for(auto i = 0; i < stmt->stmts.size(); i++) + { + auto type = stmt->stmts.at(i).as_node->type; + + if(type == gsc::node_t::asm_create || type == gsc::node_t::asm_remove) + { + stmt->stmts.erase(stmt->stmts.begin() + i); + i--; + } + } +} + +void decompiler::process_stmt_call(const gsc::context_ptr& ctx, const gsc::stmt_call_ptr& stmt) +{ + process_expr_call(ctx, stmt->expr); +} + +void decompiler::process_stmt_assign(const gsc::context_ptr& ctx, const gsc::stmt_assign_ptr& stmt) +{ + process_expr_assign(ctx, stmt->expr); +} + +void decompiler::process_stmt_endon(const gsc::context_ptr& ctx, const gsc::stmt_endon_ptr& stmt) +{ + process_expr(ctx, stmt->expr); + process_expr(ctx, stmt->obj); +} + +void decompiler::process_stmt_notify(const gsc::context_ptr& ctx, const gsc::stmt_notify_ptr& stmt) +{ + process_expr_arguments(ctx, stmt->args); + process_expr(ctx, stmt->expr); + process_expr(ctx, stmt->obj); +} + +void decompiler::process_stmt_wait(const gsc::context_ptr& ctx, const gsc::stmt_wait_ptr& stmt) +{ + process_expr(ctx, stmt->expr); +} + +void decompiler::process_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt) +{ + process_expr(ctx, stmt->expr); + process_expr(ctx, stmt->obj); + + for(auto& arg : stmt->args->list) + { + process_expr(ctx, arg); + } +} + +void decompiler::process_stmt_waittillmatch(const gsc::context_ptr& ctx, const gsc::stmt_waittillmatch_ptr& stmt) +{ + process_expr_arguments(ctx, stmt->args); + process_expr(ctx, stmt->expr); + process_expr(ctx, stmt->obj); +} + +void decompiler::process_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt) +{ + process_expr(ctx, stmt->expr); + + stmt->ctx = std::make_unique(); + ctx->transfer_decompiler(stmt->ctx); + + process_stmt(stmt->ctx, stmt->stmt); + + if(stmt->stmt.as_list->stmts.size() == 1 && !gsc::node::is_special_stmt(stmt->stmt.as_list->stmts.at(0))) + { + stmt->stmt = std::move(stmt->stmt.as_list->stmts.back()); + } +} + +void decompiler::process_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt) +{ + process_expr(ctx, stmt->expr); + + stmt->ctx_if = std::make_unique(); + ctx->transfer_decompiler(stmt->ctx_if); + + process_stmt(stmt->ctx_if, stmt->stmt_if); + + stmt->ctx_else = std::make_unique(); + ctx->transfer_decompiler(stmt->ctx_else); + + process_stmt(stmt->ctx_else, stmt->stmt_else); + + std::vector childs({stmt->ctx_if.get(), stmt->ctx_else.get()}); + ctx->append(childs); + + if(stmt->stmt_if.as_list->stmts.size() == 1 && !gsc::node::is_special_stmt(stmt->stmt_if.as_list->stmts.at(0))) + { + stmt->stmt_if = std::move(stmt->stmt_if.as_list->stmts.back()); + } + + if(stmt->stmt_else.as_list->stmts.size() == 1 && !gsc::node::is_special_stmt_noif(stmt->stmt_else.as_list->stmts.at(0))) + { + stmt->stmt_else = std::move(stmt->stmt_else.as_list->stmts.back()); + } +} + +void decompiler::process_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt) +{ + process_expr(ctx, stmt->expr); + + stmt->ctx = std::make_unique(); + ctx->transfer_decompiler(stmt->ctx); + + process_stmt(stmt->ctx, stmt->stmt); + + std::vector childs({ stmt->ctx.get() }); + + if(stmt->expr.as_node->type == gsc::node_t::null) + ctx->append_decompiler(stmt->ctx); + + if(stmt->stmt.as_list->stmts.size() == 1 && !gsc::node::is_special_stmt(stmt->stmt.as_list->stmts.at(0))) + { + stmt->stmt = std::move(stmt->stmt.as_list->stmts.back()); + } +} + +void decompiler::process_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt) +{ + process_stmt(ctx, stmt->pre_expr); + + for(auto& index : stmt->vars) + { + auto var = utils::string::va("var_%d", std::stoi(index)); + ctx->local_vars.push_back({ var, static_cast(std::stoi(index)), true }); + ctx->local_vars_create_count++; + } + + stmt->ctx = std::make_unique(); + ctx->transfer_decompiler(stmt->ctx); + + process_expr(ctx, stmt->expr); + + process_stmt(stmt->ctx, stmt->stmt); + + process_stmt(ctx, stmt->post_expr); + + if(stmt->expr.as_node->type == gsc::node_t::null) + ctx->append_decompiler(stmt->ctx); + + if(stmt->stmt.as_list->stmts.size() == 1 && !gsc::node::is_special_stmt(stmt->stmt.as_list->stmts.at(0))) + { + stmt->stmt = std::move(stmt->stmt.as_list->stmts.back()); + } +} + +void decompiler::process_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt) +{ + process_stmt(ctx, stmt->pre_expr); + + for(auto& index : stmt->vars) + { + auto var1 = utils::string::va("var_%d", std::stoi(index)); + ctx->local_vars.push_back({ var1, static_cast(std::stoi(index)), true }); + ctx->local_vars_create_count++; + } + + stmt->ctx = std::make_unique(); + ctx->transfer_decompiler(stmt->ctx); + + process_stmt(stmt->ctx, stmt->stmt0); + process_stmt(stmt->ctx, stmt->stmt); + + if(stmt->stmt.as_list->stmts.size() == 1 && !gsc::node::is_special_stmt(stmt->stmt.as_list->stmts.at(0))) + { + stmt->stmt = std::move(stmt->stmt.as_list->stmts.back()); + } + + stmt->array_expr = std::move(stmt->pre_expr.as_list->stmts[0].as_assign->expr->rvalue); + stmt->value_expr = std::move(stmt->stmt0.as_assign->expr->lvalue); + stmt->key_expr = std::move(stmt->pre_expr.as_list->stmts[1].as_assign->expr->lvalue); +} + +void decompiler::process_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt) +{ + process_expr(ctx, stmt->expr); + + stmt->ctx = std::make_unique(); + ctx->transfer_decompiler(stmt->ctx); + + process_stmt_cases(stmt->ctx, stmt->stmt); + + ctx->append_decompiler(stmt->ctx, true); +} + +void decompiler::process_stmt_cases(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt) +{ + std::vector childs; + bool has_default = false; + + for(auto& entry : stmt->stmts) + { + if(entry.as_node->type == gsc::node_t::stmt_case) + { + entry.as_case->ctx = std::make_unique(); + ctx->transfer_decompiler(entry.as_case->ctx); + + process_stmt_list(entry.as_case->ctx, entry.as_case->stmt); + + if(entry.as_case->ctx->abort == gsc::abort_t::abort_break) + { + childs.push_back(entry.as_case->ctx.get()); + } + } + else if(entry.as_node->type == gsc::node_t::stmt_default) + { + has_default = true; + entry.as_default->ctx = std::make_unique(); + ctx->transfer_decompiler(entry.as_default->ctx); + + process_stmt_list(entry.as_default->ctx, entry.as_default->stmt); + + if(entry.as_default->ctx->abort == gsc::abort_t::abort_break) + { + childs.push_back(entry.as_default->ctx.get()); + } + } + } + + if(has_default) + { + ctx->append(childs); + } +} + +void decompiler::process_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt) +{ + ctx->abort = gsc::abort_t::abort_break; +} + +void decompiler::process_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt) +{ + if(stmt->expr.as_node->type == gsc::node_t::null) + { + return; + } + + process_expr(ctx, stmt->expr); +} + +void decompiler::process_expr(const gsc::context_ptr& ctx, gsc::expr_ptr& expr) +{ + switch(expr.as_node->type) + { + case gsc::node_t::expr_increment: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_decrement: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_equal: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_add: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_sub: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_mult: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_div: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_mod: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_shift_left: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_shift_right: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_bitwise_or: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_bitwise_and: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_assign_bitwise_exor: process_expr_assign(ctx, expr.as_assign); break; + case gsc::node_t::expr_ternary: process_expr_ternary(ctx, expr.as_ternary); break; + case gsc::node_t::expr_and: process_expr_and(ctx, expr.as_and); break; + case gsc::node_t::expr_or: process_expr_or(ctx, expr.as_or); break; + case gsc::node_t::expr_equality: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_inequality: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_less: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_greater: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_less_equal: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_greater_equal: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_bitwise_or: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_bitwise_and: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_bitwise_exor: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_shift_left: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_shift_right: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_add: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_sub: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_mult: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_div: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_mod: process_expr_binary(ctx, expr.as_binary); break; + case gsc::node_t::expr_complement: process_expr_complement(ctx, expr.as_complement); break; + case gsc::node_t::expr_not: process_expr_not(ctx, expr.as_not); break; + case gsc::node_t::expr_call: process_expr_call(ctx, expr.as_call); break; + case gsc::node_t::expr_function: process_expr_function(ctx, expr.as_function); break; + case gsc::node_t::expr_add_array: process_expr_add_array(ctx, expr.as_add_array); break; + case gsc::node_t::expr_array: process_array_variable(ctx, expr.as_array); break; + case gsc::node_t::expr_field: process_field_variable(ctx, expr.as_field); break; + case gsc::node_t::expr_size: process_expr_size(ctx, expr.as_size); break; + case gsc::node_t::data_name: process_local_variable(ctx, expr.as_name); break; + case gsc::node_t::data_vector: process_vector(ctx, expr.as_vector); break; + case gsc::node_t::asm_create: process_var_create(ctx, expr); break; + case gsc::node_t::asm_access: process_var_access(ctx, expr); break; + default: break; + } +} + +void decompiler::process_expr_assign(const gsc::context_ptr& ctx, gsc::expr_assign_ptr& expr) +{ + if(expr->type == gsc::node_t::expr_increment) + { + process_expr(ctx, expr->lvalue); + } + else if(expr->type == gsc::node_t::expr_decrement) + { + process_expr(ctx, expr->lvalue); + } + else + { + process_expr(ctx, expr->rvalue); + process_expr(ctx, expr->lvalue); + + if(expr->type == gsc::node_t::expr_assign_equal) + { + switch(expr->rvalue.as_node->type) + { + case gsc::node_t::expr_bitwise_or: + if(expr->lvalue == expr->rvalue.as_bitwise_or->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_bitwise_and: + if(expr->lvalue == expr->rvalue.as_bitwise_and->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_bitwise_exor: + if(expr->lvalue == expr->rvalue.as_bitwise_exor->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_shift_left: + if(expr->lvalue == expr->rvalue.as_shift_left->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_shift_right: + if(expr->lvalue == expr->rvalue.as_shift_right->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_add: + if(expr->lvalue == expr->rvalue.as_add->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_sub: + if(expr->lvalue == expr->rvalue.as_sub->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_mult: + if(expr->lvalue == expr->rvalue.as_mult->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_div: + if(expr->lvalue == expr->rvalue.as_div->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + case gsc::node_t::expr_mod: + if(expr->lvalue == expr->rvalue.as_mod->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mod->rvalue)); + break; + default: + break; + } + } + } +} + +void decompiler::process_expr_ternary(const gsc::context_ptr& ctx, const gsc::expr_ternary_ptr& expr) +{ + process_expr(ctx, expr->cond); + process_expr(ctx, expr->lvalue); + process_expr(ctx, expr->rvalue); +} + +void decompiler::process_expr_binary(const gsc::context_ptr& ctx, const gsc::expr_binary_ptr& expr) +{ + process_expr(ctx, expr->lvalue); + process_expr(ctx, expr->rvalue); + + auto prec = expr->lvalue.as_node->precedence(); + + if(prec && prec < expr->precedence()) + { + expr->lvalue = expr_ptr(std::make_unique(std::move(expr->lvalue))); + } + + prec = expr->rvalue.as_node->precedence(); + + if(prec && prec < expr->precedence() || (prec == expr->precedence() && expr->type == expr->rvalue.as_node->type)) + { + expr->rvalue = expr_ptr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_and(const gsc::context_ptr& ctx, const gsc::expr_and_ptr& expr) +{ + process_expr(ctx, expr->lvalue); + process_expr(ctx, expr->rvalue); + + auto prec = expr->lvalue.as_node->precedence(); + + if(prec && prec < expr->precedence()) + { + expr->lvalue = expr_ptr(std::make_unique(std::move(expr->lvalue))); + } + + prec = expr->rvalue.as_node->precedence(); + + if(prec && prec < expr->precedence() || (prec == expr->precedence() && expr->type == expr->rvalue.as_node->type)) + { + expr->rvalue = expr_ptr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_or(const gsc::context_ptr& ctx, const gsc::expr_or_ptr& expr) +{ + process_expr(ctx, expr->lvalue); + process_expr(ctx, expr->rvalue); +} + +void decompiler::process_expr_complement(const gsc::context_ptr& ctx, const gsc::expr_complement_ptr& expr) +{ + process_expr(ctx, expr->rvalue); + + if(expr->rvalue.as_node->is_binary()) + { + expr->rvalue = expr_ptr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_not(const gsc::context_ptr& ctx, const gsc::expr_not_ptr& expr) +{ + process_expr(ctx, expr->rvalue); + + if(expr->rvalue.as_node->is_binary()) + { + expr->rvalue = expr_ptr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_call(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr) +{ + if(expr->func.as_node->type == gsc::node_t::expr_call_pointer) + { + process_expr_call_pointer(ctx, expr); + } + else + { + process_expr_call_function(ctx, expr); + } +} + +void decompiler::process_expr_call_pointer(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr) +{ + process_expr_arguments(ctx, expr->func.as_pointer->args); + + if(expr->obj.as_node->type != gsc::node_t::null) + process_expr(ctx, expr->obj); + + process_expr(ctx, expr->func.as_pointer->expr); +} + +void decompiler::process_expr_call_function(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr) +{ + process_expr_arguments(ctx, expr->func.as_func->args); + + if(expr->obj.as_node->type != gsc::node_t::null) + process_expr(ctx, expr->obj); +} + +void decompiler::process_expr_arguments(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& args) +{ + for(auto i = args->list.size(); i > 0; i--) + { + process_expr(ctx, args->list.at(i - 1)); + } +} + +void decompiler::process_expr_function(const gsc::context_ptr& ctx, const gsc::expr_function_ptr& expr) +{ + return; +} + +void decompiler::process_expr_add_array(const gsc::context_ptr& ctx, const gsc::expr_add_array_ptr& expr) +{ + for(auto& arg : expr->args->list) + { + process_expr(ctx, arg); + } +} + +void decompiler::process_expr_size(const gsc::context_ptr& ctx, const gsc::expr_size_ptr& expr) +{ + process_expr(ctx, expr->obj); +} + +void decompiler::process_array_variable(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr) +{ + process_expr(ctx, expr->key); + process_expr(ctx, expr->obj); +} + +void decompiler::process_field_variable(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr) +{ + process_expr(ctx, expr->obj); +} + +void decompiler::process_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr) +{ + return; +} + +void decompiler::process_vector(const gsc::context_ptr& ctx, const gsc::vector_ptr& vec) +{ + process_expr(ctx, vec->z); + process_expr(ctx, vec->y); + process_expr(ctx, vec->x); +} + +void decompiler::process_var_create(const gsc::context_ptr& ctx, gsc::expr_ptr& expr, bool fromstmt) +{ + if(fromstmt) + { + auto var = utils::string::va("var_%d", std::stoi(expr.as_asm_create->index)); + ctx->local_vars.push_back({ var, static_cast(std::stoi(expr.as_asm_create->index)), true }); + ctx->local_vars_create_count++; + } + else + { + for(auto& entry : expr.as_asm_create->vars) + { + ctx->local_vars.push_back({ utils::string::va("var_%d", std::stoi(entry)), static_cast(std::stoi(entry)), true }); + ctx->local_vars_create_count++; + } + + auto var = utils::string::va("var_%d", std::stoi(expr.as_asm_create->index)); + ctx->local_vars.push_back({ var, static_cast(std::stoi(expr.as_asm_create->index)), true }); + ctx->local_vars_create_count++; + + expr = gsc::expr_ptr(std::make_unique(var)); + } +} + +void decompiler::process_var_access(const gsc::context_ptr& ctx, gsc::expr_ptr& expr) +{ + if(ctx->local_vars.size() <= std::stoi(expr.as_asm_access->index)) + { + printf("WARNING: bad local var access\n"); + } + else + { + auto var = ctx->local_vars.at(ctx->local_vars.size() - 1 - std::stoi(expr.as_asm_access->index)).name; + expr = gsc::expr_ptr(std::make_unique(var)); + } +} + +void decompiler::process_var_remove(const gsc::context_ptr& ctx, const gsc::asm_remove_ptr& expr) +{ + ctx->local_vars_public_count = ctx->local_vars.size() - std::stoi(expr->index); +} + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/decompiler.hpp b/src/s4/xsk/decompiler.hpp new file mode 100644 index 00000000..5b004723 --- /dev/null +++ b/src/s4/xsk/decompiler.hpp @@ -0,0 +1,95 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#pragma once + +namespace xsk::gsc::s4 +{ + +class decompiler : public gsc::decompiler +{ + std::string filename_; + std::unique_ptr output_; + gsc::program_ptr program_; + gsc::thread_ptr func_; + std::unordered_map labels_; + std::vector expr_labels_; + std::vector tern_labels_; + std::stack stack_; + std::vector blocks_; + +public: + auto output() -> std::vector; + void decompile(const std::string& file, std::vector& functions); + +private: + void decompile_function(const gsc::function_ptr& func); + void decompile_statements(const gsc::function_ptr& func); + void decompile_expr(); + void decompile_ternary(); + void decompile_block(const gsc::stmt_list_ptr& block); + void decompile_search_infinite(const gsc::stmt_list_ptr& block); + void decompile_search_loop(const gsc::stmt_list_ptr& block); + void decompile_search_switch(const gsc::stmt_list_ptr& block); + void decompile_search_ifelse(const gsc::stmt_list_ptr& block); + void decompile_break_continue(const gsc::stmt_list_ptr& block); + void decompile_if(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_ifelse(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_last_ifelse(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_infinite(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_loop(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_while(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_for(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_foreach(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end); + void decompile_switch(const gsc::stmt_list_ptr& block, std::uint32_t start); + auto find_location_reference(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end, const std::string& location) -> bool; + auto find_location_index(const gsc::stmt_list_ptr& block, const std::string& location) -> std::uint32_t; + auto last_location_index(const gsc::stmt_list_ptr& block, std::uint32_t index) -> bool; + void process_stack(const gsc::thread_ptr& thread); + void process_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params); + void process_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt); + void process_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt); + void process_stmt_call(const gsc::context_ptr& ctx, const gsc::stmt_call_ptr& stmt); + void process_stmt_assign(const gsc::context_ptr& ctx, const gsc::stmt_assign_ptr& stmt); + void process_stmt_endon(const gsc::context_ptr& ctx, const gsc::stmt_endon_ptr& stmt); + void process_stmt_notify(const gsc::context_ptr& ctx, const gsc::stmt_notify_ptr& stmt); + void process_stmt_wait(const gsc::context_ptr& ctx, const gsc::stmt_wait_ptr& stmt); + void process_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt); + void process_stmt_waittillmatch(const gsc::context_ptr& ctx, const gsc::stmt_waittillmatch_ptr& stmt); + void process_stmt_waittillframeend(const gsc::context_ptr& ctx, const gsc::stmt_waittillframeend_ptr& stmt); + void process_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt); + void process_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt); + void process_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt); + void process_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt); + void process_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt); + void process_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt); + void process_stmt_cases(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt); + void process_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt); + void process_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt); + void process_expr(const gsc::context_ptr& ctx, gsc::expr_ptr& expr); + void process_expr_assign(const gsc::context_ptr& ctx, gsc::expr_assign_ptr& expr); + void process_expr_ternary(const gsc::context_ptr& ctx, const gsc::expr_ternary_ptr& expr); + void process_expr_binary(const gsc::context_ptr& ctx, const gsc::expr_binary_ptr& expr); + void process_expr_and(const gsc::context_ptr& ctx, const gsc::expr_and_ptr& expr); + void process_expr_or(const gsc::context_ptr& ctx, const gsc::expr_or_ptr& expr); + void process_expr_complement(const gsc::context_ptr& ctx, const gsc::expr_complement_ptr& expr); + void process_expr_not(const gsc::context_ptr& ctx, const gsc::expr_not_ptr& expr); + void process_expr_call(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr); + void process_expr_call_pointer(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr); + void process_expr_call_function(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr); + void process_expr_arguments(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& arg_list); + void process_expr_function(const gsc::context_ptr& ctx, const gsc::expr_function_ptr& node); + void process_expr_add_array(const gsc::context_ptr& ctx, const gsc::expr_add_array_ptr& expr); + void process_expr_size(const gsc::context_ptr& ctx, const gsc::expr_size_ptr& expr); + void process_array_variable(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr); + void process_field_variable(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr); + void process_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr); + void process_vector(const gsc::context_ptr& ctx, const gsc::vector_ptr& vec); + void process_var_create(const gsc::context_ptr& ctx, gsc::expr_ptr& expr, bool fromstmt = false); + void process_var_access(const gsc::context_ptr& ctx, gsc::expr_ptr& expr); + void process_var_remove(const gsc::context_ptr& ctx, const gsc::asm_remove_ptr& expr); +}; + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/disassembler.cpp b/src/s4/xsk/disassembler.cpp new file mode 100644 index 00000000..a3ba6c62 --- /dev/null +++ b/src/s4/xsk/disassembler.cpp @@ -0,0 +1,644 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#include "stdafx.hpp" +#include "s4.hpp" + +namespace xsk::gsc::s4 +{ + +auto disassembler::output() -> std::vector +{ + return std::move(functions_); +} + +auto disassembler::output_data() -> std::vector +{ + output_ = std::make_unique(0x100000); + + output_->write_string("// S4 PC GSCASM\n"); + output_->write_string("// Disassembled by https://github.com/xensik/gsc-tool\n"); + + for (auto& func : functions_) + { + this->print_function(func); + } + + std::vector output; + + output.resize(output_->pos()); + memcpy(output.data(), output_->buffer().data(), output.size()); + + return output; +} + +void disassembler::disassemble(const std::string& file, std::vector& script, std::vector& stack) +{ + filename_ = file; + script_ = std::make_unique(script); + stack_ = std::make_unique(stack); + functions_.clear(); + + script_->seek(1); + + while (stack_->is_avail() && script_->is_avail()) + { + functions_.push_back(std::make_unique()); + auto& func = functions_.back(); + + func->index = static_cast(script_->pos()); + func->size = stack_->read(); + func->id = stack_->read(); + func->name = "sub_"s + (func->id == 0 ? stack_->read_c_string() : resolver::token_name(func->id)); + + this->dissasemble_function(func); + + func->labels = labels_; + labels_.clear(); + } + + this->resolve_local_functions(); +} + +void disassembler::dissasemble_function(const gsc::function_ptr& func) +{ + auto size = func->size; + + while (size > 0) + { + func->instructions.push_back(std::make_unique()); + + auto& inst = func->instructions.back(); + inst->index = static_cast(script_->pos()); + inst->opcode = script_->read(); + inst->size = opcode_size(inst->opcode); + + this->dissasemble_instruction(inst); + + size -= inst->size; + } +} + +void disassembler::dissasemble_instruction(const gsc::instruction_ptr& inst) +{ + switch (opcode(inst->opcode)) + { + case opcode::OP_CastFieldObject: + case opcode::OP_plus: + case opcode::OP_GetGameRef: + case opcode::OP_GetThisthread: + case opcode::OP_greater: + case opcode::OP_shift_right: + case opcode::OP_dec: + case opcode::OP_bit_or: + case opcode::OP_equality: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_notify: + case opcode::OP_PreScriptCall: + case opcode::OP_GetUndefined: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_GetLevel: + case opcode::OP_size: + case opcode::OP_AddArray: + case opcode::OP_endon: + case opcode::OP_shift_left: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_Return: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_GetSelfObject: + case opcode::OP_GetGame: + case opcode::OP_EvalArray: + case opcode::OP_GetSelf: + case opcode::OP_End: + case opcode::OP_less_equal: + case opcode::OP_EvalLocalVariableCached0: + case opcode::OP_EvalLocalVariableCached1: + case opcode::OP_EvalLocalVariableCached2: + case opcode::OP_EvalLocalVariableCached3: + case opcode::OP_EvalLocalVariableCached4: + case opcode::OP_EvalLocalVariableCached5: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_checkclearparams: + case opcode::OP_waittillmatch2: + case opcode::OP_minus: + case opcode::OP_greater_equal: + case opcode::OP_vector: + case opcode::OP_ClearArray: + case opcode::OP_DecTop: + case opcode::OP_CastBool: + case opcode::OP_EvalArrayRef: + case opcode::OP_GetZero: + case opcode::OP_wait: + case opcode::OP_waittill: + case opcode::OP_GetAnimObject: + case opcode::OP_mod: + case opcode::OP_clearparams: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_EmptyArray: + case opcode::OP_ClearVariableField: + case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_BoolComplement: + case opcode::OP_less: + case opcode::OP_BoolNot: + case opcode::OP_waittillFrameEnd: + case opcode::OP_waitframe: + case opcode::OP_GetLevelObject: + case opcode::OP_inc: + case opcode::OP_GetAnim: + case opcode::OP_SetVariableField: + case opcode::OP_divide: + case opcode::OP_multiply: + case opcode::OP_EvalLocalVariableRefCached0: + case opcode::OP_bit_and: + case opcode::OP_voidCodepos: + case opcode::OP_inequality: + case opcode::OP_bit_ex_or: +// case opcode::OP_NOP: +// case opcode::OP_abort: +// case opcode::OP_object: +// case opcode::OP_thread_object: + case opcode::OP_EvalLocalVariable: + case opcode::OP_EvalLocalVariableRef: +// case opcode::OP_breakpoint: +// case opcode::OP_assignmentBreakpoint: +// case opcode::OP_manualAndAssignmentBreakpoint: + case opcode::OP_BoolNotAfterAnd: + case opcode::OP_IsDefined: + case opcode::OP_IsTrue: + break; + case opcode::OP_GetByte: + case opcode::OP_GetNegByte: + inst->data.push_back(utils::string::va("%i", script_->read())); + break; + case opcode::OP_GetUnsignedShort: + case opcode::OP_GetNegUnsignedShort: + inst->data.push_back(utils::string::va("%i", script_->read())); + break; + case opcode::OP_GetInteger: + inst->data.push_back(utils::string::va("%i", script_->read())); + break; + case opcode::OP_GetFloat: + { + auto val = script_->read(); + inst->data.push_back(utils::string::va("%g%s", val, val == int(val) ? ".0" : "")); + } + break; + case opcode::OP_GetVector: + inst->data.push_back(utils::string::va("%g", script_->read())); + inst->data.push_back(utils::string::va("%g", script_->read())); + inst->data.push_back(utils::string::va("%g", script_->read())); + break; + case opcode::OP_GetString: + case opcode::OP_GetIString: + script_->seek(4); + inst->data.push_back(utils::string::to_literal(stack_->read_c_string())); + break; + case opcode::OP_GetAnimation: + script_->seek(8); + inst->data.push_back(utils::string::quote(stack_->read_c_string().data(), false)); + inst->data.push_back(utils::string::quote(stack_->read_c_string().data(), false)); + break; + case opcode::OP_GetAnimTree: + script_->seek(1); + inst->data.push_back(utils::string::quote(stack_->read_c_string().data(), false)); + break; + case opcode::OP_waittillmatch: + inst->data.push_back(utils::string::va("%i", script_->read())); + break; + case opcode::OP_SetNewLocalVariableFieldCached0: + case opcode::OP_EvalNewLocalArrayRefCached0: + case opcode::OP_SafeCreateVariableFieldCached: + case opcode::OP_ClearLocalVariableFieldCached: + case opcode::OP_SetLocalVariableFieldCached: + case opcode::OP_RemoveLocalVariables: + case opcode::OP_EvalLocalVariableRefCached: + case opcode::OP_EvalLocalArrayRefCached: + case opcode::OP_SafeSetVariableFieldCached: + case opcode::OP_EvalLocalVariableCached: + case opcode::OP_SafeSetWaittillVariableFieldCached: + case opcode::OP_CreateLocalVariable: + case opcode::OP_EvalLocalVariableObjectCached: + case opcode::OP_EvalLocalArrayCached: + inst->data.push_back(utils::string::va("%i", script_->read())); + break; + case opcode::OP_EvalSelfFieldVariable: + case opcode::OP_SetLevelFieldVariableField: + case opcode::OP_ClearFieldVariable: + case opcode::OP_EvalFieldVariable: + case opcode::OP_EvalFieldVariableRef: + case opcode::OP_EvalLevelFieldVariable: + case opcode::OP_SetAnimFieldVariableField: + case opcode::OP_SetSelfFieldVariableField: + case opcode::OP_EvalAnimFieldVariableRef: + case opcode::OP_EvalLevelFieldVariableRef: + case opcode::OP_EvalAnimFieldVariable: + case opcode::OP_EvalSelfFieldVariableRef: + this->disassemble_field_variable(inst); + break; + case opcode::OP_CallBuiltinPointer: + case opcode::OP_CallBuiltinMethodPointer: + case opcode::OP_ScriptThreadCallPointer: + case opcode::OP_ScriptChildThreadCallPointer: + case opcode::OP_ScriptMethodThreadCallPointer: + case opcode::OP_ScriptMethodChildThreadCallPointer: + inst->data.push_back(utils::string::va("%i", script_->read())); + break; + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalMethodCall: + this->disassemble_local_call(inst, false); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + this->disassemble_local_call(inst, true); + break; + case opcode::OP_GetFarFunction: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarMethodCall: + this->disassemble_far_call(inst, false); + break; + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_ScriptFarMethodChildThreadCall: + this->disassemble_far_call(inst, true); + break; + case opcode::OP_CallBuiltin: + this->disassemble_builtin_call(inst, false, true); + break; + case opcode::OP_CallBuiltinMethod: + this->disassemble_builtin_call(inst, true, true); + break; + case opcode::OP_GetBuiltinFunction: + case opcode::OP_CallBuiltin0: + case opcode::OP_CallBuiltin1: + case opcode::OP_CallBuiltin2: + case opcode::OP_CallBuiltin3: + case opcode::OP_CallBuiltin4: + case opcode::OP_CallBuiltin5: + this->disassemble_builtin_call(inst, false, false); + break; + case opcode::OP_GetBuiltinMethod: + case opcode::OP_CallBuiltinMethod0: + case opcode::OP_CallBuiltinMethod1: + case opcode::OP_CallBuiltinMethod2: + case opcode::OP_CallBuiltinMethod3: + case opcode::OP_CallBuiltinMethod4: + case opcode::OP_CallBuiltinMethod5: + this->disassemble_builtin_call(inst, true, false); + break; + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + this->disassemble_jump(inst, true, false); + break; + case opcode::OP_jumpback: + this->disassemble_jump(inst, false, true); + break; + case opcode::OP_jump: + this->disassemble_jump(inst, false, false); + break; + case opcode::OP_switch: + this->disassemble_switch(inst); + break; + case opcode::OP_endswitch: + this->disassemble_end_switch(inst); + break; +/* + case opcode::OP_prof_begin: + script_->seek(5); // TODO: skipped data + break; + case opcode::OP_prof_end: + script_->seek(1); // TODO: skipped data + break; + case opcode::OP_EvalNewLocalArrayRefCached0_Precompiled: + case opcode::OP_SetNewLocalVariableFieldCached0_Precompiled: + case opcode::OP_CreateLocalVariable_Precompiled: + case opcode::OP_SafeCreateVariableFieldCached_Precompiled: + inst->data.push_back(utils::string::va("%i", script_->read())); + break; +*/ + case opcode::OP_FormalParams: + case opcode::OP_FormalParams_Precompiled: + this->disassemble_formal_params(inst); + break; +/* case opcode::OP_NativeGetLocalFunction: + case opcode::OP_NativeLocalFunctionCall: + case opcode::OP_NativeLocalFunctionCall2: + case opcode::OP_NativeLocalMethodCall: + this->disassemble_local_call(inst, false); + break; + case opcode::OP_NativeGetFarFunction: + case opcode::OP_NativeFarFunctionCall: + case opcode::OP_NativeFarFunctionCall2: + case opcode::OP_NativeFarMethodCall: + this->disassemble_far_call(inst, false); + break; + case opcode::OP_NativeLocalFunctionThreadCall: + case opcode::OP_NativeLocalMethodThreadCall: + case opcode::OP_NativeLocalFunctionChildThreadCall: + case opcode::OP_NativeLocalMethodChildThreadCall: + this->disassemble_local_call(inst, true); + break; + case opcode::OP_NativeFarFunctionThreadCall: + case opcode::OP_NativeFarMethodThreadCall: + case opcode::OP_NativeFarFunctionChildThreadCall: + case opcode::OP_NativeFarMethodChildThreadCall: + this->disassemble_far_call(inst, true); + break; +*/ + default: + throw gsc::disasm_error(utils::string::va("Unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index)); + } +} + +void disassembler::disassemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num) +{ + if (arg_num) + { + inst->data.push_back(utils::string::va("%i", script_->read())); + } + + if (method) + { + inst->data.push_back(resolver::method_name(script_->read())); + } + else + { + inst->data.push_back(resolver::function_name(script_->read())); + } +} + +void disassembler::disassemble_local_call(const gsc::instruction_ptr& inst, bool thread) +{ + std::int32_t offset = this->disassemble_offset(); + + inst->data.push_back(utils::string::va("%X", offset + inst->index + 1)); + + if (thread) + { + inst->data.push_back(utils::string::va("%i", script_->read())); + } +} + +void disassembler::disassemble_far_call(const gsc::instruction_ptr& inst, bool thread) +{ + script_->seek(3); + + if (thread) + { + inst->data.push_back(utils::string::va("%i", script_->read())); + } + + auto file_id = stack_->read(); + auto file_name = file_id == 0 ? stack_->read_c_string() : resolver::file_name(file_id); + auto func_id = stack_->read(); + auto func_name = func_id == 0 ? stack_->read_c_string() : resolver::token_name(func_id); + + inst->data.push_back(file_name != "" ? file_name : utils::string::va("_ID%i", file_id)); + inst->data.push_back(func_name != "" ? func_name : utils::string::va("_ID%i", func_id)); +} + +void disassembler::disassemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back) +{ + std::int32_t addr; + std::string label; + + if (expr) + { + addr = inst->index + 3 + script_->read(); + label = utils::string::va("loc_%X", addr); + inst->data.push_back(label); + } + else if (back) + { + addr = inst->index + 3 - script_->read(); + label = utils::string::va("loc_%X", addr); + inst->data.push_back(label); + } + else + { + addr = inst->index + 5 + script_->read(); + label = utils::string::va("loc_%X", addr); + inst->data.push_back(label); + } + + labels_.insert({addr, label}); +} + +void disassembler::disassemble_field_variable(const gsc::instruction_ptr& inst) +{ + std::uint32_t field_id = script_->read(); + std::string field_name; + + if(field_id > 0x1C000) + { + auto temp = stack_->read(); + field_name = temp == 0 ? stack_->read_c_string() : std::to_string(temp); + } + else + { + field_name = resolver::token_name(field_id); + } + + inst->data.push_back(field_name != "" ? field_name : utils::string::va("_ID%i", field_id)); +} + +void disassembler::disassemble_formal_params(const gsc::instruction_ptr& inst) +{ + auto size = script_->read(); + + inst->size += size; + inst->data.push_back(utils::string::va("%i", size)); + + while(size > 0) + { + inst->data.push_back(utils::string::va("%d", script_->read())); + size--; + } +} + +void disassembler::disassemble_switch(const gsc::instruction_ptr& inst) +{ + std::int32_t addr = inst->index + 4 + script_->read(); + std::string label = utils::string::va("loc_%X", addr); + + inst->data.push_back(label); + labels_.insert({addr, label}); +} + +void disassembler::disassemble_end_switch(const gsc::instruction_ptr& inst) +{ + std::uint16_t case_num = script_->read(); + inst->data.push_back(utils::string::va("%i", case_num)); + + std::uint32_t internal_index = inst->index + 3; + + if (case_num) + { + for (auto i = case_num; i > 0; i--) + { + std::uint32_t case_label = script_->read(); + + if (case_label < 0x80000 && case_label > 0) + { + inst->data.push_back("case"); + inst->data.push_back(utils::string::quote(stack_->read_c_string(), false)); + } + else if (case_label == 0) + { + inst->data.push_back("default"); + stack_->read(); + } + else + { + inst->data.push_back("case"); + inst->data.push_back(utils::string::va("%i", (case_label - 0x800000) & 0xFFFFFF)); + } + + inst->size += 4; + internal_index += 4; + + auto addr = this->disassemble_offset() + internal_index; + std::string label = utils::string::va("loc_%X", addr); + inst->data.push_back(label); + + labels_.insert({addr, label}); + + inst->size += 3; + internal_index += 3; + } + } +} + +auto disassembler::disassemble_offset() -> std::int32_t +{ + std::array bytes = {}; + + for (auto i = 0; i < 3; i++) + { + bytes[i] = script_->read(); + } + + std::int32_t offset = *reinterpret_cast(bytes.data()); + + offset = (offset << 8) >> 8; + + return offset; +} + +void disassembler::resolve_local_functions() +{ + for (auto& func : functions_) + { + for (auto& inst : func->instructions) + { + switch (opcode(inst->opcode)) + { + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalMethodCall: + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + inst->data.at(0) = this->resolve_function(inst->data[0]); + break; + default: + break; + } + } + } +} + +auto disassembler::resolve_function(const std::string& index) -> std::string +{ + if (utils::string::is_hex_number(index)) + { + std::uint32_t idx = std::stoul(index, nullptr, 16); + + for (auto& func : functions_) + { + if (func->index == idx) + { + return func->name; + } + } + + throw gsc::disasm_error(utils::string::va("Couldn't resolve function name at index '0x%04X'!", idx)); + } + + throw gsc::disasm_error(utils::string::va("\"%s\" is not valid function address!", index.data())); +} + +void disassembler::print_function(const gsc::function_ptr& func) +{ + output_->write_string("\n"); + output_->write_string(utils::string::va("%s\n", func->name.data())); + + for (auto& inst : func->instructions) + { + const auto itr = func->labels.find(inst->index); + + if (itr != func->labels.end()) + { + output_->write_string(utils::string::va("\t%s\n", itr->second.data())); + } + + this->print_instruction(inst); + } + + output_->write_string("\n"); + output_->write_string(utils::string::va("end_%s\n", func->name.substr(4).data())); +} + +void disassembler::print_instruction(const gsc::instruction_ptr& inst) +{ + switch (opcode(inst->opcode)) + { + case opcode::OP_endswitch: + output_->write_string(utils::string::va("\t\t%s", resolver::opcode_name(inst->opcode).data())); + output_->write_string(utils::string::va(" %s\n", inst->data[0].data())); + { + std::uint32_t totalcase = std::stoul(inst->data[0]); + auto index = 0; + for (auto casenum = 0u; casenum < totalcase; casenum++) + { + if (inst->data[1 + index] == "case") + { + output_->write_string(utils::string::va("\t\t\t%s %s %s", inst->data[1 + index].data(), inst->data[1 + index + 1].data(), inst->data[1 + index + 2].data())); + index += 3; + } + else if (inst->data[1 + index] == "default") + { + output_->write_string(utils::string::va("\t\t\t%s %s", inst->data[1 + index].data(), inst->data[1 + index + 1].data())); + index += 2; + } + if (casenum != totalcase - 1) + { + output_->write_string("\n"); + } + } + } + break; + default: + output_->write_string(utils::string::va("\t\t%s", resolver::opcode_name(inst->opcode).data())); + for (auto& d : inst->data) + { + output_->write_string(utils::string::va(" %s", d.data())); + } + break; + } + + output_->write_string("\n"); +} + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/disassembler.hpp b/src/s4/xsk/disassembler.hpp new file mode 100644 index 00000000..2084e013 --- /dev/null +++ b/src/s4/xsk/disassembler.hpp @@ -0,0 +1,43 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#pragma once + +namespace xsk::gsc::s4 +{ + +class disassembler : public gsc::disassembler +{ + std::string filename_; + utils::byte_buffer_ptr script_; + utils::byte_buffer_ptr stack_; + utils::byte_buffer_ptr output_; + std::vector functions_; + std::unordered_map labels_; + +public: + auto output() -> std::vector; + auto output_data() -> std::vector; + void disassemble(const std::string& file, std::vector& script, std::vector& stack); + +private: + void dissasemble_function(const gsc::function_ptr& func); + void dissasemble_instruction(const gsc::instruction_ptr& inst); + void disassemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num); + void disassemble_local_call(const gsc::instruction_ptr& inst, bool thread); + void disassemble_far_call(const gsc::instruction_ptr& inst, bool thread); + void disassemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back); + void disassemble_field_variable(const gsc::instruction_ptr& inst); + void disassemble_formal_params(const gsc::instruction_ptr& inst); + void disassemble_switch(const gsc::instruction_ptr& inst); + void disassemble_end_switch(const gsc::instruction_ptr& inst); + auto disassemble_offset() -> std::int32_t; + void resolve_local_functions(); + auto resolve_function(const std::string& index) -> std::string; + void print_function(const gsc::function_ptr& func); + void print_instruction(const gsc::instruction_ptr& inst); +}; + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/lexer.cpp b/src/s4/xsk/lexer.cpp new file mode 100644 index 00000000..1c4e3b4f --- /dev/null +++ b/src/s4/xsk/lexer.cpp @@ -0,0 +1,2882 @@ +#line 1 "lexer.cpp" +#include "stdafx.hpp" +#include "s4.hpp" +#include "parser.hpp" +using namespace xsk::gsc; + +#line 7 "lexer.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define s4__create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer s4__create_buffer +#endif + +#ifdef yy_delete_buffer +#define s4__delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer s4__delete_buffer +#endif + +#ifdef yy_scan_buffer +#define s4__scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer s4__scan_buffer +#endif + +#ifdef yy_scan_string +#define s4__scan_string_ALREADY_DEFINED +#else +#define yy_scan_string s4__scan_string +#endif + +#ifdef yy_scan_bytes +#define s4__scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes s4__scan_bytes +#endif + +#ifdef yy_init_buffer +#define s4__init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer s4__init_buffer +#endif + +#ifdef yy_flush_buffer +#define s4__flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer s4__flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define s4__load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state s4__load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define s4__switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer s4__switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define s4_push_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state s4_push_buffer_state +#endif + +#ifdef yypop_buffer_state +#define s4_pop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state s4_pop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define s4_ensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack s4_ensure_buffer_stack +#endif + +#ifdef yylex +#define s4_lex_ALREADY_DEFINED +#else +#define yylex s4_lex +#endif + +#ifdef yyrestart +#define s4_restart_ALREADY_DEFINED +#else +#define yyrestart s4_restart +#endif + +#ifdef yylex_init +#define s4_lex_init_ALREADY_DEFINED +#else +#define yylex_init s4_lex_init +#endif + +#ifdef yylex_init_extra +#define s4_lex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra s4_lex_init_extra +#endif + +#ifdef yylex_destroy +#define s4_lex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy s4_lex_destroy +#endif + +#ifdef yyget_debug +#define s4_get_debug_ALREADY_DEFINED +#else +#define yyget_debug s4_get_debug +#endif + +#ifdef yyset_debug +#define s4_set_debug_ALREADY_DEFINED +#else +#define yyset_debug s4_set_debug +#endif + +#ifdef yyget_extra +#define s4_get_extra_ALREADY_DEFINED +#else +#define yyget_extra s4_get_extra +#endif + +#ifdef yyset_extra +#define s4_set_extra_ALREADY_DEFINED +#else +#define yyset_extra s4_set_extra +#endif + +#ifdef yyget_in +#define s4_get_in_ALREADY_DEFINED +#else +#define yyget_in s4_get_in +#endif + +#ifdef yyset_in +#define s4_set_in_ALREADY_DEFINED +#else +#define yyset_in s4_set_in +#endif + +#ifdef yyget_out +#define s4_get_out_ALREADY_DEFINED +#else +#define yyget_out s4_get_out +#endif + +#ifdef yyset_out +#define s4_set_out_ALREADY_DEFINED +#else +#define yyset_out s4_set_out +#endif + +#ifdef yyget_leng +#define s4_get_leng_ALREADY_DEFINED +#else +#define yyget_leng s4_get_leng +#endif + +#ifdef yyget_text +#define s4_get_text_ALREADY_DEFINED +#else +#define yyget_text s4_get_text +#endif + +#ifdef yyget_lineno +#define s4_get_lineno_ALREADY_DEFINED +#else +#define yyget_lineno s4_get_lineno +#endif + +#ifdef yyset_lineno +#define s4_set_lineno_ALREADY_DEFINED +#else +#define yyset_lineno s4_set_lineno +#endif + +#ifdef yyget_column +#define s4_get_column_ALREADY_DEFINED +#else +#define yyget_column s4_get_column +#endif + +#ifdef yyset_column +#define s4_set_column_ALREADY_DEFINED +#else +#define yyset_column s4_set_column +#endif + +#ifdef yywrap +#define s4_wrap_ALREADY_DEFINED +#else +#define yywrap s4_wrap +#endif + +#ifdef yyalloc +#define s4_alloc_ALREADY_DEFINED +#else +#define yyalloc s4_alloc +#endif + +#ifdef yyrealloc +#define s4_realloc_ALREADY_DEFINED +#else +#define yyrealloc s4_realloc +#endif + +#ifdef yyfree +#define s4_free_ALREADY_DEFINED +#else +#define yyfree s4_free +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin , yyscanner ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +static void yyensure_buffer_stack ( yyscan_t yyscanner ); +static void yy_load_buffer_state ( yyscan_t yyscanner ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define s4_wrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); +static int yy_get_next_buffer ( yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; +#define YY_NUM_RULES 102 +#define YY_END_OF_BUFFER 103 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[300] = + { 0, + 0, 0, 0, 0, 0, 0, 103, 101, 1, 2, + 86, 101, 101, 85, 89, 101, 46, 47, 83, 81, + 52, 82, 53, 84, 100, 100, 55, 56, 70, 80, + 71, 57, 92, 50, 51, 90, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 48, 88, 49, 87, 5, 6, 5, 9, 10, + 9, 67, 0, 94, 0, 0, 0, 0, 0, 76, + 0, 65, 0, 78, 0, 0, 74, 58, 72, 59, + 73, 96, 8, 4, 3, 75, 96, 100, 97, 0, + 0, 0, 0, 54, 62, 68, 66, 69, 63, 92, + + 79, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 22, 27, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 77, 64, 7, 11, 0, + 94, 0, 0, 0, 0, 0, 0, 93, 0, 0, + 0, 0, 94, 0, 96, 3, 96, 96, 97, 98, + 99, 91, 60, 61, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 25, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 95, 0, + 0, 0, 0, 93, 0, 0, 93, 0, 44, 92, + 37, 29, 92, 92, 92, 23, 92, 92, 92, 42, + + 92, 92, 92, 43, 41, 92, 92, 92, 38, 92, + 17, 92, 0, 0, 0, 0, 31, 92, 92, 92, + 15, 39, 92, 45, 92, 92, 92, 92, 92, 92, + 92, 92, 24, 0, 0, 0, 0, 92, 92, 92, + 92, 16, 33, 28, 92, 34, 92, 92, 92, 95, + 0, 0, 0, 92, 92, 30, 26, 92, 92, 92, + 92, 0, 12, 0, 92, 32, 92, 92, 92, 18, + 14, 0, 92, 92, 40, 21, 92, 92, 0, 92, + 36, 92, 92, 0, 35, 92, 92, 0, 92, 92, + 0, 92, 19, 0, 92, 13, 92, 20, 0 + + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 20, 20, 20, 20, 20, 21, 21, 22, 23, 24, + 25, 26, 27, 1, 28, 29, 28, 28, 28, 28, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 31, 30, 30, + 32, 33, 34, 35, 36, 1, 37, 38, 39, 40, + + 41, 42, 43, 44, 45, 30, 46, 47, 48, 49, + 50, 30, 30, 51, 52, 53, 54, 55, 56, 31, + 57, 58, 59, 60, 61, 62, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static const YY_CHAR yy_meta[63] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 4, 4, 4, + 4, 1, 1, 1, 1, 1, 1, 4, 4, 5, + 5, 1, 6, 1, 1, 5, 4, 4, 4, 4, + 4, 4, 5, 5, 7, 5, 5, 5, 5, 5, + 5, 5, 5, 7, 5, 5, 5, 5, 1, 1, + 1, 1 + } ; + +static const flex_int16_t yy_base[320] = + { 0, + 0, 0, 60, 61, 62, 63, 643, 644, 644, 644, + 617, 62, 33, 616, 66, 67, 644, 644, 615, 64, + 644, 65, 63, 80, 83, 90, 617, 644, 69, 613, + 92, 644, 604, 644, 644, 611, 80, 74, 82, 55, + 87, 91, 94, 97, 102, 100, 104, 107, 105, 109, + 118, 644, 97, 644, 644, 644, 644, 618, 644, 644, + 617, 644, 139, 644, 156, 0, 584, 583, 579, 644, + 142, 644, 144, 644, 145, 157, 644, 644, 644, 644, + 644, 149, 644, 644, 0, 644, 161, 167, 176, 160, + 183, 201, 0, 644, 605, 644, 644, 644, 604, 595, + + 644, 165, 132, 171, 179, 178, 172, 46, 131, 198, + 174, 180, 594, 593, 151, 182, 193, 200, 199, 203, + 204, 211, 218, 217, 219, 644, 644, 644, 644, 248, + 249, 256, 0, 580, 585, 578, 251, 644, 263, 254, + 264, 260, 261, 268, 644, 0, 284, 644, 290, 267, + 0, 589, 644, 644, 227, 239, 241, 257, 245, 246, + 258, 274, 279, 280, 281, 283, 284, 285, 286, 294, + 287, 288, 298, 301, 302, 304, 300, 305, 0, 573, + 573, 570, 334, 339, 343, 338, 340, 348, 585, 322, + 584, 583, 321, 325, 323, 582, 326, 333, 327, 581, + + 332, 336, 329, 580, 579, 349, 330, 352, 578, 351, + 353, 357, 0, 557, 555, 565, 574, 354, 359, 358, + 573, 572, 361, 571, 363, 364, 366, 368, 369, 370, + 371, 378, 570, 0, 551, 561, 564, 381, 383, 385, + 384, 566, 565, 564, 388, 563, 386, 393, 394, 644, + 554, 553, 556, 391, 399, 559, 558, 403, 410, 398, + 400, 549, 644, 540, 412, 555, 415, 416, 417, 421, + 644, 542, 422, 424, 553, 537, 427, 428, 514, 433, + 482, 434, 429, 461, 457, 435, 437, 438, 439, 441, + 447, 446, 453, 440, 442, 644, 444, 401, 644, 491, + + 498, 505, 509, 516, 521, 525, 532, 425, 539, 546, + 553, 560, 564, 276, 571, 578, 204, 170, 81 + } ; + +static const flex_int16_t yy_def[320] = + { 0, + 299, 1, 300, 300, 301, 301, 299, 299, 299, 299, + 299, 302, 303, 299, 299, 304, 299, 299, 299, 299, + 299, 299, 299, 299, 305, 305, 299, 299, 299, 299, + 299, 299, 306, 299, 299, 299, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 302, 299, 307, 308, 308, 299, 299, 299, + 309, 299, 310, 299, 304, 311, 299, 299, 299, 299, + 299, 299, 299, 299, 312, 299, 299, 305, 305, 305, + 305, 305, 313, 299, 299, 299, 299, 299, 299, 306, + + 299, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 299, 299, 299, 299, 302, + 302, 307, 314, 299, 299, 299, 309, 299, 315, 310, + 316, 304, 304, 311, 299, 312, 299, 299, 305, 305, + 92, 313, 299, 299, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 317, 299, + 299, 299, 309, 309, 315, 310, 310, 316, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 318, 299, 299, 299, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 319, 299, 299, 299, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 299, + 299, 299, 299, 306, 306, 306, 306, 306, 306, 306, + 306, 299, 299, 299, 306, 306, 306, 306, 306, 306, + 299, 299, 306, 306, 306, 306, 306, 306, 299, 306, + 306, 306, 306, 299, 306, 306, 306, 299, 306, 306, + 299, 306, 306, 299, 306, 299, 306, 306, 0, 299, + + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299 + } ; + +static const flex_int16_t yy_nxt[707] = + { 0, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, + 26, 27, 28, 29, 30, 31, 32, 33, 33, 33, + 33, 34, 8, 35, 36, 33, 37, 38, 39, 40, + 41, 42, 43, 33, 44, 33, 45, 33, 46, 33, + 47, 48, 49, 50, 33, 51, 33, 33, 52, 53, + 54, 55, 57, 57, 60, 60, 64, 61, 61, 67, + 71, 58, 58, 72, 73, 64, 78, 68, 93, 80, + 82, 82, 82, 82, 250, 83, 69, 93, 79, 81, + 74, 84, 95, 96, 65, 107, 85, 162, 87, 76, + + 88, 89, 89, 88, 86, 87, 93, 88, 88, 88, + 88, 91, 93, 92, 93, 93, 98, 99, 104, 93, + 91, 126, 93, 93, 103, 105, 93, 110, 102, 93, + 112, 106, 93, 108, 93, 109, 93, 93, 113, 93, + 111, 93, 115, 64, 117, 114, 138, 118, 121, 116, + 93, 119, 138, 64, 124, 122, 127, 123, 63, 75, + 131, 125, 120, 93, 93, 143, 82, 82, 82, 82, + 163, 65, 156, 234, 139, 299, 141, 76, 147, 147, + 147, 147, 87, 93, 88, 88, 88, 88, 132, 144, + 145, 87, 93, 149, 149, 149, 88, 93, 299, 93, + + 150, 150, 148, 93, 93, 167, 93, 213, 93, 155, + 93, 93, 93, 161, 93, 93, 299, 157, 151, 151, + 151, 151, 158, 159, 165, 93, 160, 166, 151, 151, + 93, 93, 93, 93, 168, 93, 93, 151, 151, 151, + 151, 151, 151, 93, 164, 169, 170, 172, 173, 93, + 93, 93, 64, 64, 174, 138, 171, 176, 63, 93, + 131, 177, 138, 178, 175, 137, 140, 184, 64, 64, + 75, 93, 187, 93, 189, 190, 143, 93, 93, 179, + 65, 65, 299, 139, 150, 150, 141, 191, 132, 93, + 93, 193, 76, 76, 195, 185, 188, 192, 194, 93, + + 144, 147, 147, 147, 147, 87, 93, 149, 149, 149, + 88, 93, 93, 93, 196, 93, 93, 93, 93, 93, + 93, 199, 93, 200, 201, 148, 93, 205, 197, 202, + 93, 198, 93, 93, 93, 204, 93, 93, 138, 203, + 206, 208, 209, 138, 210, 137, 138, 184, 138, 207, + 140, 212, 211, 93, 93, 93, 187, 93, 93, 93, + 218, 93, 93, 223, 93, 93, 139, 217, 93, 219, + 141, 139, 141, 222, 221, 185, 220, 225, 224, 226, + 188, 93, 228, 93, 93, 93, 93, 227, 229, 93, + 93, 93, 230, 93, 231, 93, 93, 233, 93, 241, + + 93, 93, 93, 93, 240, 232, 238, 239, 246, 244, + 93, 245, 243, 93, 247, 93, 93, 93, 93, 242, + 93, 248, 249, 93, 254, 93, 93, 257, 133, 260, + 93, 93, 93, 93, 259, 93, 255, 256, 258, 266, + 261, 265, 93, 267, 93, 269, 270, 93, 93, 93, + 268, 274, 273, 93, 93, 275, 93, 276, 280, 93, + 93, 93, 277, 281, 283, 93, 93, 93, 278, 93, + 286, 93, 285, 93, 93, 290, 93, 282, 93, 292, + 296, 287, 289, 298, 293, 93, 295, 294, 291, 93, + 297, 56, 56, 56, 56, 56, 56, 56, 59, 59, + + 59, 59, 59, 59, 59, 63, 63, 63, 63, 63, + 63, 63, 66, 288, 93, 66, 75, 75, 75, 75, + 75, 75, 75, 90, 90, 90, 90, 90, 100, 100, + 100, 100, 130, 130, 130, 130, 130, 130, 130, 137, + 137, 137, 137, 137, 137, 137, 140, 140, 140, 140, + 140, 140, 140, 142, 142, 142, 142, 142, 142, 142, + 146, 284, 146, 146, 146, 146, 146, 152, 152, 93, + 152, 183, 183, 183, 183, 183, 183, 183, 186, 186, + 186, 186, 186, 186, 186, 93, 279, 93, 272, 271, + 93, 93, 264, 263, 262, 93, 93, 93, 93, 253, + + 252, 251, 93, 93, 93, 93, 93, 237, 236, 235, + 93, 93, 93, 93, 93, 93, 93, 93, 216, 215, + 214, 93, 182, 181, 180, 93, 93, 93, 154, 153, + 136, 135, 134, 129, 128, 101, 93, 97, 94, 77, + 70, 62, 299, 7, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + + 299, 299, 299, 299, 299, 299 + } ; + +static const flex_int16_t yy_chk[707] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 4, 5, 6, 12, 5, 6, 13, + 15, 3, 4, 15, 15, 16, 20, 13, 108, 22, + 23, 23, 23, 23, 319, 24, 13, 40, 20, 22, + 15, 24, 29, 29, 12, 40, 24, 108, 25, 16, + + 25, 25, 25, 25, 24, 26, 38, 26, 26, 26, + 26, 25, 37, 25, 39, 25, 31, 31, 39, 41, + 25, 53, 26, 42, 38, 39, 43, 42, 37, 44, + 43, 39, 46, 41, 45, 41, 47, 49, 44, 48, + 42, 50, 45, 63, 47, 44, 71, 48, 49, 46, + 51, 48, 73, 75, 51, 49, 53, 50, 65, 76, + 65, 51, 48, 109, 103, 76, 82, 82, 82, 82, + 109, 63, 103, 318, 71, 90, 73, 75, 87, 87, + 87, 87, 88, 115, 88, 88, 88, 88, 65, 76, + 82, 89, 90, 89, 89, 89, 89, 102, 91, 88, + + 91, 91, 87, 104, 107, 115, 111, 317, 89, 102, + 106, 105, 112, 107, 116, 91, 92, 104, 92, 92, + 92, 92, 104, 105, 111, 117, 106, 112, 92, 92, + 110, 119, 118, 92, 116, 120, 121, 92, 92, 92, + 92, 92, 92, 122, 110, 117, 118, 120, 121, 124, + 123, 125, 130, 131, 121, 137, 119, 123, 132, 155, + 132, 124, 140, 125, 122, 139, 141, 139, 142, 143, + 144, 156, 141, 157, 155, 156, 144, 159, 160, 314, + 130, 131, 150, 137, 150, 150, 140, 157, 132, 158, + 161, 159, 142, 143, 161, 139, 141, 158, 160, 150, + + 144, 147, 147, 147, 147, 149, 162, 149, 149, 149, + 149, 163, 164, 165, 162, 166, 167, 168, 169, 171, + 172, 165, 149, 166, 167, 147, 170, 171, 163, 168, + 173, 164, 177, 174, 175, 170, 176, 178, 183, 169, + 172, 174, 175, 184, 176, 185, 186, 185, 187, 173, + 188, 178, 177, 193, 190, 195, 188, 194, 197, 199, + 193, 203, 207, 199, 201, 198, 183, 190, 202, 194, + 186, 184, 187, 198, 197, 185, 195, 202, 201, 203, + 188, 206, 207, 210, 208, 211, 218, 206, 208, 212, + 220, 219, 210, 223, 211, 225, 226, 212, 227, 223, + + 228, 229, 230, 231, 220, 211, 218, 219, 229, 227, + 232, 228, 226, 238, 230, 239, 241, 240, 247, 225, + 245, 231, 232, 254, 238, 248, 249, 241, 308, 248, + 260, 255, 261, 298, 247, 258, 239, 240, 245, 255, + 249, 254, 259, 258, 265, 260, 261, 267, 268, 269, + 259, 267, 265, 270, 273, 268, 274, 269, 273, 277, + 278, 283, 270, 274, 278, 280, 282, 286, 270, 287, + 282, 289, 280, 290, 295, 287, 297, 277, 292, 289, + 294, 283, 286, 297, 290, 293, 292, 291, 288, 285, + 295, 300, 300, 300, 300, 300, 300, 300, 301, 301, + + 301, 301, 301, 301, 301, 302, 302, 302, 302, 302, + 302, 302, 303, 284, 281, 303, 304, 304, 304, 304, + 304, 304, 304, 305, 305, 305, 305, 305, 306, 306, + 306, 306, 307, 307, 307, 307, 307, 307, 307, 309, + 309, 309, 309, 309, 309, 309, 310, 310, 310, 310, + 310, 310, 310, 311, 311, 311, 311, 311, 311, 311, + 312, 279, 312, 312, 312, 312, 312, 313, 313, 276, + 313, 315, 315, 315, 315, 315, 315, 315, 316, 316, + 316, 316, 316, 316, 316, 275, 272, 266, 264, 262, + 257, 256, 253, 252, 251, 246, 244, 243, 242, 237, + + 236, 235, 233, 224, 222, 221, 217, 216, 215, 214, + 209, 205, 204, 200, 196, 192, 191, 189, 182, 181, + 180, 152, 136, 135, 134, 114, 113, 100, 99, 95, + 69, 68, 67, 61, 58, 36, 33, 30, 27, 19, + 14, 11, 7, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + + 299, 299, 299, 299, 299, 299 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "lexer.lpp" +/* Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. +*/ +#define YY_NO_INPUT 1 +#define YY_NO_UNISTD_H 1 + +#line 23 "lexer.lpp" +#define YY_USER_ACTION loc.columns(yyleng); +#line 905 "lexer.cpp" + +#line 907 "lexer.cpp" + +#define INITIAL 0 +#define COMMENT_BLOCK_STATE 1 +#define DEVELOPER_BLOCK_STATE 2 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + }; /* end struct yyguts_t */ + +static int yy_init_globals ( yyscan_t yyscanner ); + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + + int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( yyscan_t yyscanner ); +#else +static int input ( yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_load_buffer_state( yyscanner ); + } + + { +#line 40 "lexer.lpp" + + + +#line 44 "lexer.lpp" + loc.step(); + + +#line 1175 "lexer.cpp" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 300 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_current_state != 299 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 47 "lexer.lpp" +{ loc.step(); } + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 49 "lexer.lpp" +{ loc.lines(yyleng); loc.step(); } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 51 "lexer.lpp" + + YY_BREAK +case 4: +YY_RULE_SETUP +#line 53 "lexer.lpp" +{ BEGIN(COMMENT_BLOCK_STATE); } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 54 "lexer.lpp" + + YY_BREAK +case 6: +/* rule 6 can match eol */ +YY_RULE_SETUP +#line 55 "lexer.lpp" +{ loc.lines(yyleng); loc.step(); } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 56 "lexer.lpp" +{ BEGIN(INITIAL); } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 58 "lexer.lpp" +{ BEGIN(DEVELOPER_BLOCK_STATE); } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 59 "lexer.lpp" + + YY_BREAK +case 10: +/* rule 10 can match eol */ +YY_RULE_SETUP +#line 60 "lexer.lpp" +{ loc.lines(yyleng); loc.step(); } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 61 "lexer.lpp" +{ BEGIN(INITIAL); } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 63 "lexer.lpp" +{ return s4::parser::make_INCLUDE(loc); } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 64 "lexer.lpp" +{ return s4::parser::make_USINGTREE(loc); } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 65 "lexer.lpp" +{ return s4::parser::make_ANIMTREE(loc); } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 66 "lexer.lpp" +{ return s4::parser::make_ENDON(loc); } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 67 "lexer.lpp" +{ return s4::parser::make_NOTIFY(loc); } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 68 "lexer.lpp" +{ return s4::parser::make_WAIT(loc); } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 69 "lexer.lpp" +{ return s4::parser::make_WAITTILL(loc); } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 70 "lexer.lpp" +{ return s4::parser::make_WAITTILLMATCH(loc); } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 71 "lexer.lpp" +{ return s4::parser::make_WAITTILLFRAMEEND(loc); } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 72 "lexer.lpp" +{ return s4::parser::make_WAITFRAME(loc); } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 73 "lexer.lpp" +{ return s4::parser::make_IF(loc); } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 74 "lexer.lpp" +{ return s4::parser::make_ELSE(loc); } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 75 "lexer.lpp" +{ return s4::parser::make_WHILE(loc); } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 76 "lexer.lpp" +{ return s4::parser::make_FOR(loc); } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 77 "lexer.lpp" +{ return s4::parser::make_FOREACH(loc); } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 78 "lexer.lpp" +{ return s4::parser::make_IN(loc); } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 79 "lexer.lpp" +{ return s4::parser::make_SWITCH(loc); } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 80 "lexer.lpp" +{ return s4::parser::make_CASE(loc); } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 81 "lexer.lpp" +{ return s4::parser::make_DEFAULT(loc); } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 82 "lexer.lpp" +{ return s4::parser::make_BREAK(loc); } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 83 "lexer.lpp" +{ return s4::parser::make_CONTINUE(loc); } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 84 "lexer.lpp" +{ return s4::parser::make_RETURN(loc); } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 85 "lexer.lpp" +{ return s4::parser::make_THREAD(loc); } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 86 "lexer.lpp" +{ return s4::parser::make_CHILDTHREAD(loc); } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 87 "lexer.lpp" +{ return s4::parser::make_THISTHREAD(loc); } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 88 "lexer.lpp" +{ return s4::parser::make_CALL(loc); } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 89 "lexer.lpp" +{ return s4::parser::make_TRUE(loc); } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 90 "lexer.lpp" +{ return s4::parser::make_FALSE(loc); } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 91 "lexer.lpp" +{ return s4::parser::make_UNDEFINED(loc); } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 92 "lexer.lpp" +{ return s4::parser::make_SIZE(loc); } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 93 "lexer.lpp" +{ return s4::parser::make_GAME(loc); } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 94 "lexer.lpp" +{ return s4::parser::make_SELF(loc); } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 95 "lexer.lpp" +{ return s4::parser::make_ANIM(loc); } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 96 "lexer.lpp" +{ return s4::parser::make_LEVEL(loc); } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 97 "lexer.lpp" +{ return s4::parser::make_LPAREN(loc); } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 98 "lexer.lpp" +{ return s4::parser::make_RPAREN(loc); } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 99 "lexer.lpp" +{ return s4::parser::make_LBRACE(loc); } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 100 "lexer.lpp" +{ return s4::parser::make_RBRACE(loc); } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 101 "lexer.lpp" +{ return s4::parser::make_LBRACKET(loc); } + YY_BREAK +case 51: +YY_RULE_SETUP +#line 102 "lexer.lpp" +{ return s4::parser::make_RBRACKET(loc); } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 103 "lexer.lpp" +{ return s4::parser::make_COMMA(loc); } + YY_BREAK +case 53: +YY_RULE_SETUP +#line 104 "lexer.lpp" +{ return s4::parser::make_DOT(loc); } + YY_BREAK +case 54: +YY_RULE_SETUP +#line 105 "lexer.lpp" +{ return s4::parser::make_DOUBLECOLON(loc); } + YY_BREAK +case 55: +YY_RULE_SETUP +#line 106 "lexer.lpp" +{ return s4::parser::make_COLON(loc); } + YY_BREAK +case 56: +YY_RULE_SETUP +#line 107 "lexer.lpp" +{ return s4::parser::make_SEMICOLON(loc); } + YY_BREAK +case 57: +YY_RULE_SETUP +#line 108 "lexer.lpp" +{ return s4::parser::make_QMARK(loc); } + YY_BREAK +case 58: +YY_RULE_SETUP +#line 109 "lexer.lpp" +{ return s4::parser::make_INCREMENT(loc); } + YY_BREAK +case 59: +YY_RULE_SETUP +#line 110 "lexer.lpp" +{ return s4::parser::make_DECREMENT(loc); } + YY_BREAK +case 60: +YY_RULE_SETUP +#line 111 "lexer.lpp" +{ return s4::parser::make_ASSIGN_LSHIFT(loc); } + YY_BREAK +case 61: +YY_RULE_SETUP +#line 112 "lexer.lpp" +{ return s4::parser::make_ASSIGN_RSHIFT(loc); } + YY_BREAK +case 62: +YY_RULE_SETUP +#line 113 "lexer.lpp" +{ return s4::parser::make_LSHIFT(loc); } + YY_BREAK +case 63: +YY_RULE_SETUP +#line 114 "lexer.lpp" +{ return s4::parser::make_RSHIFT(loc); } + YY_BREAK +case 64: +YY_RULE_SETUP +#line 115 "lexer.lpp" +{ return s4::parser::make_OR(loc); } + YY_BREAK +case 65: +YY_RULE_SETUP +#line 116 "lexer.lpp" +{ return s4::parser::make_AND(loc); } + YY_BREAK +case 66: +YY_RULE_SETUP +#line 117 "lexer.lpp" +{ return s4::parser::make_EQUALITY(loc); } + YY_BREAK +case 67: +YY_RULE_SETUP +#line 118 "lexer.lpp" +{ return s4::parser::make_INEQUALITY(loc); } + YY_BREAK +case 68: +YY_RULE_SETUP +#line 119 "lexer.lpp" +{ return s4::parser::make_LESS_EQUAL(loc); } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 120 "lexer.lpp" +{ return s4::parser::make_GREATER_EQUAL(loc); } + YY_BREAK +case 70: +YY_RULE_SETUP +#line 121 "lexer.lpp" +{ return s4::parser::make_LESS(loc); } + YY_BREAK +case 71: +YY_RULE_SETUP +#line 122 "lexer.lpp" +{ return s4::parser::make_GREATER(loc); } + YY_BREAK +case 72: +YY_RULE_SETUP +#line 123 "lexer.lpp" +{ return s4::parser::make_ASSIGN_ADD(loc); } + YY_BREAK +case 73: +YY_RULE_SETUP +#line 124 "lexer.lpp" +{ return s4::parser::make_ASSIGN_SUB(loc); } + YY_BREAK +case 74: +YY_RULE_SETUP +#line 125 "lexer.lpp" +{ return s4::parser::make_ASSIGN_MULT(loc); } + YY_BREAK +case 75: +YY_RULE_SETUP +#line 126 "lexer.lpp" +{ return s4::parser::make_ASSIGN_DIV(loc); } + YY_BREAK +case 76: +YY_RULE_SETUP +#line 127 "lexer.lpp" +{ return s4::parser::make_ASSIGN_MOD(loc); } + YY_BREAK +case 77: +YY_RULE_SETUP +#line 128 "lexer.lpp" +{ return s4::parser::make_ASSIGN_BITWISE_OR(loc); } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 129 "lexer.lpp" +{ return s4::parser::make_ASSIGN_BITWISE_AND(loc); } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 130 "lexer.lpp" +{ return s4::parser::make_ASSIGN_BITWISE_EXOR(loc); } + YY_BREAK +case 80: +YY_RULE_SETUP +#line 131 "lexer.lpp" +{ return s4::parser::make_ASSIGN(loc); } + YY_BREAK +case 81: +YY_RULE_SETUP +#line 132 "lexer.lpp" +{ return s4::parser::make_ADD(loc); } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 133 "lexer.lpp" +{ return s4::parser::make_SUB(loc); } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 134 "lexer.lpp" +{ return s4::parser::make_MULT(loc); } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 135 "lexer.lpp" +{ return s4::parser::make_DIV(loc); } + YY_BREAK +case 85: +YY_RULE_SETUP +#line 136 "lexer.lpp" +{ return s4::parser::make_MOD(loc); } + YY_BREAK +case 86: +YY_RULE_SETUP +#line 137 "lexer.lpp" +{ return s4::parser::make_NOT(loc); } + YY_BREAK +case 87: +YY_RULE_SETUP +#line 138 "lexer.lpp" +{ return s4::parser::make_COMPLEMENT(loc); } + YY_BREAK +case 88: +YY_RULE_SETUP +#line 139 "lexer.lpp" +{ return s4::parser::make_BITWISE_OR(loc); } + YY_BREAK +case 89: +YY_RULE_SETUP +#line 140 "lexer.lpp" +{ return s4::parser::make_BITWISE_AND(loc); } + YY_BREAK +case 90: +YY_RULE_SETUP +#line 141 "lexer.lpp" +{ return s4::parser::make_BITWISE_EXOR(loc); } + YY_BREAK +case 91: +YY_RULE_SETUP +#line 142 "lexer.lpp" +{ return s4::parser::make_FILE(utils::string::fordslash(yytext), loc); } + YY_BREAK +case 92: +YY_RULE_SETUP +#line 143 "lexer.lpp" +{ return s4::parser::make_NAME((std::string(yytext, 3) == "_ID") ? std::string(yytext) : utils::string::to_lower(yytext), loc); } + YY_BREAK +case 93: +/* rule 93 can match eol */ +YY_RULE_SETUP +#line 144 "lexer.lpp" +{ return s4::parser::make_ISTRING(std::string(yytext).substr(1), loc); } + YY_BREAK +case 94: +/* rule 94 can match eol */ +YY_RULE_SETUP +#line 145 "lexer.lpp" +{ return s4::parser::make_STRING(std::string(yytext), loc); } + YY_BREAK +case 95: +YY_RULE_SETUP +#line 146 "lexer.lpp" +{ return s4::parser::make_COLOR(std::string(yytext).substr(1), loc); } + YY_BREAK +case 96: +YY_RULE_SETUP +#line 147 "lexer.lpp" +{ return s4::parser::make_FLOAT(std::string(yytext), loc); } + YY_BREAK +case 97: +YY_RULE_SETUP +#line 148 "lexer.lpp" +{ return s4::parser::make_INT_OCT(utils::string::oct_to_dec(yytext), loc); } + YY_BREAK +case 98: +YY_RULE_SETUP +#line 149 "lexer.lpp" +{ return s4::parser::make_INT_BIN(utils::string::bin_to_dec(yytext), loc); } + YY_BREAK +case 99: +YY_RULE_SETUP +#line 150 "lexer.lpp" +{ return s4::parser::make_INT_HEX(utils::string::hex_to_dec(yytext), loc); } + YY_BREAK +case 100: +YY_RULE_SETUP +#line 151 "lexer.lpp" +{ return s4::parser::make_INT_DEC(std::string(yytext), loc); } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT_BLOCK_STATE): +case YY_STATE_EOF(DEVELOPER_BLOCK_STATE): +#line 152 "lexer.lpp" +{ return s4::parser::make_S4EOF(loc); } + YY_BREAK +case 101: +/* rule 101 can match eol */ +YY_RULE_SETUP +#line 153 "lexer.lpp" +{ throw s4::parser::syntax_error(loc, "bad token: \'" + std::string(yytext) + "\'"); } + YY_BREAK +case 102: +YY_RULE_SETUP +#line 155 "lexer.lpp" +ECHO; + YY_BREAK +#line 1750 "lexer.cpp" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( yywrap( yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin , yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + yy_state_type yy_current_state; + char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 300 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + char *yy_cp = yyg->yy_c_buf_p; + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 300 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 299); + + (void)yyg; + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin , yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( yyscanner ) ) + return 0; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); + yy_load_buffer_state( yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file , yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf , yyscanner ); + + yyfree( (void *) b , yyscanner ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_flush_buffer( b , yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(yyscanner); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (yyscan_t yyscanner) +{ + yy_size_t num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b , yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n , yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n , yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param _line_number line number + * @param yyscanner The scanner object. + */ +void yyset_lineno (int _line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); + + yylineno = _line_number; +} + +/** Set the current column. + * @param _column_no column number + * @param yyscanner The scanner object. + */ +void yyset_column (int _column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_column called with no buffer" ); + + yycolumn = _column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = _out_str ; +} + +int yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void yyset_debug (int _bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = _bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ +int yylex_init(yyscan_t* ptr_yy_globals) +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ +int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) +{ + struct yyguts_t dummy_yyguts; + + yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = NULL; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = NULL; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + yyfree(yyg->yy_buffer_stack , yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + yyfree( yyg->yy_start_stack , yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s , yyscan_t yyscanner) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + return malloc(size); +} + +void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree (void * ptr , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 155 "lexer.lpp" + + diff --git a/src/s4/xsk/lexer.hpp b/src/s4/xsk/lexer.hpp new file mode 100644 index 00000000..c9a4fd37 --- /dev/null +++ b/src/s4/xsk/lexer.hpp @@ -0,0 +1,708 @@ +#ifndef s4_HEADER_H +#define s4_HEADER_H 1 +#define s4_IN_HEADER 1 + +#line 5 "lexer.hpp" +#include "stdafx.hpp" +#include "s4.hpp" +#include "parser.hpp" +using namespace xsk::gsc; + +#line 11 "lexer.hpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define s4__create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer s4__create_buffer +#endif + +#ifdef yy_delete_buffer +#define s4__delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer s4__delete_buffer +#endif + +#ifdef yy_scan_buffer +#define s4__scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer s4__scan_buffer +#endif + +#ifdef yy_scan_string +#define s4__scan_string_ALREADY_DEFINED +#else +#define yy_scan_string s4__scan_string +#endif + +#ifdef yy_scan_bytes +#define s4__scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes s4__scan_bytes +#endif + +#ifdef yy_init_buffer +#define s4__init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer s4__init_buffer +#endif + +#ifdef yy_flush_buffer +#define s4__flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer s4__flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define s4__load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state s4__load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define s4__switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer s4__switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define s4_push_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state s4_push_buffer_state +#endif + +#ifdef yypop_buffer_state +#define s4_pop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state s4_pop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define s4_ensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack s4_ensure_buffer_stack +#endif + +#ifdef yylex +#define s4_lex_ALREADY_DEFINED +#else +#define yylex s4_lex +#endif + +#ifdef yyrestart +#define s4_restart_ALREADY_DEFINED +#else +#define yyrestart s4_restart +#endif + +#ifdef yylex_init +#define s4_lex_init_ALREADY_DEFINED +#else +#define yylex_init s4_lex_init +#endif + +#ifdef yylex_init_extra +#define s4_lex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra s4_lex_init_extra +#endif + +#ifdef yylex_destroy +#define s4_lex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy s4_lex_destroy +#endif + +#ifdef yyget_debug +#define s4_get_debug_ALREADY_DEFINED +#else +#define yyget_debug s4_get_debug +#endif + +#ifdef yyset_debug +#define s4_set_debug_ALREADY_DEFINED +#else +#define yyset_debug s4_set_debug +#endif + +#ifdef yyget_extra +#define s4_get_extra_ALREADY_DEFINED +#else +#define yyget_extra s4_get_extra +#endif + +#ifdef yyset_extra +#define s4_set_extra_ALREADY_DEFINED +#else +#define yyset_extra s4_set_extra +#endif + +#ifdef yyget_in +#define s4_get_in_ALREADY_DEFINED +#else +#define yyget_in s4_get_in +#endif + +#ifdef yyset_in +#define s4_set_in_ALREADY_DEFINED +#else +#define yyset_in s4_set_in +#endif + +#ifdef yyget_out +#define s4_get_out_ALREADY_DEFINED +#else +#define yyget_out s4_get_out +#endif + +#ifdef yyset_out +#define s4_set_out_ALREADY_DEFINED +#else +#define yyset_out s4_set_out +#endif + +#ifdef yyget_leng +#define s4_get_leng_ALREADY_DEFINED +#else +#define yyget_leng s4_get_leng +#endif + +#ifdef yyget_text +#define s4_get_text_ALREADY_DEFINED +#else +#define yyget_text s4_get_text +#endif + +#ifdef yyget_lineno +#define s4_get_lineno_ALREADY_DEFINED +#else +#define yyget_lineno s4_get_lineno +#endif + +#ifdef yyset_lineno +#define s4_set_lineno_ALREADY_DEFINED +#else +#define yyset_lineno s4_set_lineno +#endif + +#ifdef yyget_column +#define s4_get_column_ALREADY_DEFINED +#else +#define yyget_column s4_get_column +#endif + +#ifdef yyset_column +#define s4_set_column_ALREADY_DEFINED +#else +#define yyset_column s4_set_column +#endif + +#ifdef yywrap +#define s4_wrap_ALREADY_DEFINED +#else +#define yywrap s4_wrap +#endif + +#ifdef yyalloc +#define s4_alloc_ALREADY_DEFINED +#else +#define yyalloc s4_alloc +#endif + +#ifdef yyrealloc +#define s4_realloc_ALREADY_DEFINED +#else +#define yyrealloc s4_realloc +#endif + +#ifdef yyfree +#define s4_free_ALREADY_DEFINED +#else +#define yyfree s4_free +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +/* Begin user sect3 */ + +#define s4_wrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define COMMENT_BLOCK_STATE 1 +#define DEVELOPER_BLOCK_STATE 2 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + + int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#ifndef s4__create_buffer_ALREADY_DEFINED +#undef yy_create_buffer +#endif +#ifndef s4__delete_buffer_ALREADY_DEFINED +#undef yy_delete_buffer +#endif +#ifndef s4__scan_buffer_ALREADY_DEFINED +#undef yy_scan_buffer +#endif +#ifndef s4__scan_string_ALREADY_DEFINED +#undef yy_scan_string +#endif +#ifndef s4__scan_bytes_ALREADY_DEFINED +#undef yy_scan_bytes +#endif +#ifndef s4__init_buffer_ALREADY_DEFINED +#undef yy_init_buffer +#endif +#ifndef s4__flush_buffer_ALREADY_DEFINED +#undef yy_flush_buffer +#endif +#ifndef s4__load_buffer_state_ALREADY_DEFINED +#undef yy_load_buffer_state +#endif +#ifndef s4__switch_to_buffer_ALREADY_DEFINED +#undef yy_switch_to_buffer +#endif +#ifndef s4_push_buffer_state_ALREADY_DEFINED +#undef yypush_buffer_state +#endif +#ifndef s4_pop_buffer_state_ALREADY_DEFINED +#undef yypop_buffer_state +#endif +#ifndef s4_ensure_buffer_stack_ALREADY_DEFINED +#undef yyensure_buffer_stack +#endif +#ifndef s4_lex_ALREADY_DEFINED +#undef yylex +#endif +#ifndef s4_restart_ALREADY_DEFINED +#undef yyrestart +#endif +#ifndef s4_lex_init_ALREADY_DEFINED +#undef yylex_init +#endif +#ifndef s4_lex_init_extra_ALREADY_DEFINED +#undef yylex_init_extra +#endif +#ifndef s4_lex_destroy_ALREADY_DEFINED +#undef yylex_destroy +#endif +#ifndef s4_get_debug_ALREADY_DEFINED +#undef yyget_debug +#endif +#ifndef s4_set_debug_ALREADY_DEFINED +#undef yyset_debug +#endif +#ifndef s4_get_extra_ALREADY_DEFINED +#undef yyget_extra +#endif +#ifndef s4_set_extra_ALREADY_DEFINED +#undef yyset_extra +#endif +#ifndef s4_get_in_ALREADY_DEFINED +#undef yyget_in +#endif +#ifndef s4_set_in_ALREADY_DEFINED +#undef yyset_in +#endif +#ifndef s4_get_out_ALREADY_DEFINED +#undef yyget_out +#endif +#ifndef s4_set_out_ALREADY_DEFINED +#undef yyset_out +#endif +#ifndef s4_get_leng_ALREADY_DEFINED +#undef yyget_leng +#endif +#ifndef s4_get_text_ALREADY_DEFINED +#undef yyget_text +#endif +#ifndef s4_get_lineno_ALREADY_DEFINED +#undef yyget_lineno +#endif +#ifndef s4_set_lineno_ALREADY_DEFINED +#undef yyset_lineno +#endif +#ifndef s4_get_column_ALREADY_DEFINED +#undef yyget_column +#endif +#ifndef s4_set_column_ALREADY_DEFINED +#undef yyset_column +#endif +#ifndef s4_wrap_ALREADY_DEFINED +#undef yywrap +#endif +#ifndef s4_get_lval_ALREADY_DEFINED +#undef yyget_lval +#endif +#ifndef s4_set_lval_ALREADY_DEFINED +#undef yyset_lval +#endif +#ifndef s4_get_lloc_ALREADY_DEFINED +#undef yyget_lloc +#endif +#ifndef s4_set_lloc_ALREADY_DEFINED +#undef yyset_lloc +#endif +#ifndef s4_alloc_ALREADY_DEFINED +#undef yyalloc +#endif +#ifndef s4_realloc_ALREADY_DEFINED +#undef yyrealloc +#endif +#ifndef s4_free_ALREADY_DEFINED +#undef yyfree +#endif +#ifndef s4_text_ALREADY_DEFINED +#undef yytext +#endif +#ifndef s4_leng_ALREADY_DEFINED +#undef yyleng +#endif +#ifndef s4_in_ALREADY_DEFINED +#undef yyin +#endif +#ifndef s4_out_ALREADY_DEFINED +#undef yyout +#endif +#ifndef s4__flex_debug_ALREADY_DEFINED +#undef yy_flex_debug +#endif +#ifndef s4_lineno_ALREADY_DEFINED +#undef yylineno +#endif +#ifndef s4_tables_fload_ALREADY_DEFINED +#undef yytables_fload +#endif +#ifndef s4_tables_destroy_ALREADY_DEFINED +#undef yytables_destroy +#endif +#ifndef s4_TABLES_NAME_ALREADY_DEFINED +#undef yyTABLES_NAME +#endif + +#line 155 "lexer.lpp" + + +#line 706 "lexer.hpp" +#undef s4_IN_HEADER +#endif /* s4_HEADER_H */ diff --git a/src/s4/xsk/parser.cpp b/src/s4/xsk/parser.cpp new file mode 100644 index 00000000..2e1742f0 --- /dev/null +++ b/src/s4/xsk/parser.cpp @@ -0,0 +1,4116 @@ +// A Bison parser, made by GNU Bison 3.7.5. + +// Skeleton implementation for Bison LALR(1) parsers in C++ + +// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// As a special exception, you may create a larger work that contains +// part or all of the Bison parser skeleton and distribute that work +// under terms of your choice, so long as that work isn't itself a +// parser generator using the skeleton or a modified version thereof +// as a parser skeleton. Alternatively, if you modify or redistribute +// the parser skeleton itself, you may (at your option) remove this +// special exception, which will cause the skeleton and the resulting +// Bison output files to be licensed under the GNU General Public +// License without this special exception. + +// This special exception was added by the Free Software Foundation in +// version 2.2 of Bison. + +// DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, +// especially those whose name start with YY_ or yy_. They are +// private implementation details that can be changed or removed. + +// "%code top" blocks. +#line 40 "parser.ypp" + +#include "stdafx.hpp" +#include "parser.hpp" +#include "lexer.hpp" +using namespace xsk::gsc; +xsk::gsc::s4::parser::symbol_type S4lex(yyscan_t yyscanner, xsk::gsc::location& loc); + +#line 47 "parser.cpp" + +// Take the name prefix into account. +#define yylex S4lex + + + +#include "parser.hpp" + + + + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include // FIXME: INFRINGES ON USER NAME SPACE. +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + + +// Whether we are compiled with exception support. +#ifndef YY_EXCEPTIONS +# if defined __GNUC__ && !defined __EXCEPTIONS +# define YY_EXCEPTIONS 0 +# else +# define YY_EXCEPTIONS 1 +# endif +#endif + +#define YYRHSLOC(Rhs, K) ((Rhs)[K].location) +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +# ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).begin = YYRHSLOC (Rhs, 1).begin; \ + (Current).end = YYRHSLOC (Rhs, N).end; \ + } \ + else \ + { \ + (Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \ + } \ + while (false) +# endif + + +// Enable debugging if requested. +#if S4DEBUG + +// A pseudo ostream that takes yydebug_ into account. +# define YYCDEBUG if (yydebug_) (*yycdebug_) + +# define YY_SYMBOL_PRINT(Title, Symbol) \ + do { \ + if (yydebug_) \ + { \ + *yycdebug_ << Title << ' '; \ + yy_print_ (*yycdebug_, Symbol); \ + *yycdebug_ << '\n'; \ + } \ + } while (false) + +# define YY_REDUCE_PRINT(Rule) \ + do { \ + if (yydebug_) \ + yy_reduce_print_ (Rule); \ + } while (false) + +# define YY_STACK_PRINT() \ + do { \ + if (yydebug_) \ + yy_stack_print_ (); \ + } while (false) + +#else // !S4DEBUG + +# define YYCDEBUG if (false) std::cerr +# define YY_SYMBOL_PRINT(Title, Symbol) YY_USE (Symbol) +# define YY_REDUCE_PRINT(Rule) static_cast (0) +# define YY_STACK_PRINT() static_cast (0) + +#endif // !S4DEBUG + +#define yyerrok (yyerrstatus_ = 0) +#define yyclearin (yyla.clear ()) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYRECOVERING() (!!yyerrstatus_) + +#line 13 "parser.ypp" +namespace xsk { namespace gsc { namespace s4 { +#line 149 "parser.cpp" + + /// Build a parser object. + parser::parser (yyscan_t yyscanner_yyarg, xsk::gsc::location& loc_yyarg, xsk::gsc::program_ptr& ast_yyarg) +#if S4DEBUG + : yydebug_ (false), + yycdebug_ (&std::cerr), +#else + : +#endif + yy_lac_established_ (false), + yyscanner (yyscanner_yyarg), + loc (loc_yyarg), + ast (ast_yyarg) + {} + + parser::~parser () + {} + + parser::syntax_error::~syntax_error () YY_NOEXCEPT YY_NOTHROW + {} + + /*---------------. + | symbol kinds. | + `---------------*/ + + + + // by_state. + parser::by_state::by_state () YY_NOEXCEPT + : state (empty_state) + {} + + parser::by_state::by_state (const by_state& that) YY_NOEXCEPT + : state (that.state) + {} + + void + parser::by_state::clear () YY_NOEXCEPT + { + state = empty_state; + } + + void + parser::by_state::move (by_state& that) + { + state = that.state; + that.clear (); + } + + parser::by_state::by_state (state_type s) YY_NOEXCEPT + : state (s) + {} + + parser::symbol_kind_type + parser::by_state::kind () const YY_NOEXCEPT + { + if (state == empty_state) + return symbol_kind::S_YYEMPTY; + else + return YY_CAST (symbol_kind_type, yystos_[+state]); + } + + parser::stack_symbol_type::stack_symbol_type () + {} + + parser::stack_symbol_type::stack_symbol_type (YY_RVREF (stack_symbol_type) that) + : super_type (YY_MOVE (that.state), YY_MOVE (that.location)) + { + switch (that.kind ()) + { + case symbol_kind::S_anim: // anim + value.YY_MOVE_OR_COPY< anim_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_animation: // animation + value.YY_MOVE_OR_COPY< animation_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_animtree: // animtree + value.YY_MOVE_OR_COPY< animtree_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_color: // color + value.YY_MOVE_OR_COPY< color_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_constant: // constant + value.YY_MOVE_OR_COPY< constant_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_define: // define + value.YY_MOVE_OR_COPY< define_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_empty_array: // empty_array + value.YY_MOVE_OR_COPY< empty_array_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.YY_MOVE_OR_COPY< expr_arguments_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.YY_MOVE_OR_COPY< expr_assign_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.YY_MOVE_OR_COPY< expr_call_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.YY_MOVE_OR_COPY< expr_call_type_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.YY_MOVE_OR_COPY< expr_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_false: // false + value.YY_MOVE_OR_COPY< false_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_file: // file + value.YY_MOVE_OR_COPY< file_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_float: // float + value.YY_MOVE_OR_COPY< float_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_game: // game + value.YY_MOVE_OR_COPY< game_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.YY_MOVE_OR_COPY< include_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_integer: // integer + value.YY_MOVE_OR_COPY< integer_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_istring: // istring + value.YY_MOVE_OR_COPY< istring_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_level: // level + value.YY_MOVE_OR_COPY< level_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_name: // name + value.YY_MOVE_OR_COPY< name_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.YY_MOVE_OR_COPY< node_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_parameters: // parameters + value.YY_MOVE_OR_COPY< parameters_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.YY_MOVE_OR_COPY< program_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_self: // self + value.YY_MOVE_OR_COPY< self_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.YY_MOVE_OR_COPY< std::string > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.YY_MOVE_OR_COPY< stmt_assign_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.YY_MOVE_OR_COPY< stmt_break_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.YY_MOVE_OR_COPY< stmt_call_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.YY_MOVE_OR_COPY< stmt_case_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.YY_MOVE_OR_COPY< stmt_continue_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.YY_MOVE_OR_COPY< stmt_default_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.YY_MOVE_OR_COPY< stmt_endon_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.YY_MOVE_OR_COPY< stmt_for_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.YY_MOVE_OR_COPY< stmt_foreach_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.YY_MOVE_OR_COPY< stmt_if_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.YY_MOVE_OR_COPY< stmt_ifelse_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.YY_MOVE_OR_COPY< stmt_list_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.YY_MOVE_OR_COPY< stmt_notify_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.YY_MOVE_OR_COPY< stmt_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.YY_MOVE_OR_COPY< stmt_return_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.YY_MOVE_OR_COPY< stmt_switch_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.YY_MOVE_OR_COPY< stmt_wait_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.YY_MOVE_OR_COPY< stmt_waitframe_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.YY_MOVE_OR_COPY< stmt_waittill_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.YY_MOVE_OR_COPY< stmt_waittillframeend_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.YY_MOVE_OR_COPY< stmt_waittillmatch_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.YY_MOVE_OR_COPY< stmt_while_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_string: // string + value.YY_MOVE_OR_COPY< string_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_thisthread: // thisthread + value.YY_MOVE_OR_COPY< thisthread_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_thread: // thread + value.YY_MOVE_OR_COPY< thread_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_true: // true + value.YY_MOVE_OR_COPY< true_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_undefined: // undefined + value.YY_MOVE_OR_COPY< undefined_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_usingtree: // usingtree + value.YY_MOVE_OR_COPY< usingtree_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_vector: // vector + value.YY_MOVE_OR_COPY< vector_ptr > (YY_MOVE (that.value)); + break; + + default: + break; + } + +#if 201103L <= YY_CPLUSPLUS + // that is emptied. + that.state = empty_state; +#endif + } + + parser::stack_symbol_type::stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) that) + : super_type (s, YY_MOVE (that.location)) + { + switch (that.kind ()) + { + case symbol_kind::S_anim: // anim + value.move< anim_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_animation: // animation + value.move< animation_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_animtree: // animtree + value.move< animtree_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_color: // color + value.move< color_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_constant: // constant + value.move< constant_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_define: // define + value.move< define_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_empty_array: // empty_array + value.move< empty_array_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.move< expr_arguments_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.move< expr_assign_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.move< expr_call_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.move< expr_call_type_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.move< expr_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_false: // false + value.move< false_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_file: // file + value.move< file_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_float: // float + value.move< float_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_game: // game + value.move< game_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.move< include_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_integer: // integer + value.move< integer_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_istring: // istring + value.move< istring_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_level: // level + value.move< level_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_name: // name + value.move< name_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.move< node_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_parameters: // parameters + value.move< parameters_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.move< program_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_self: // self + value.move< self_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.move< std::string > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< stmt_assign_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< stmt_break_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< stmt_call_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< stmt_case_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< stmt_continue_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< stmt_default_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< stmt_endon_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< stmt_for_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< stmt_foreach_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< stmt_if_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< stmt_ifelse_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.move< stmt_list_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< stmt_notify_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.move< stmt_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< stmt_return_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< stmt_switch_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< stmt_wait_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< stmt_waitframe_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< stmt_waittill_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< stmt_waittillframeend_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< stmt_waittillmatch_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< stmt_while_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_string: // string + value.move< string_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_thisthread: // thisthread + value.move< thisthread_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_thread: // thread + value.move< thread_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_true: // true + value.move< true_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_undefined: // undefined + value.move< undefined_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_usingtree: // usingtree + value.move< usingtree_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_vector: // vector + value.move< vector_ptr > (YY_MOVE (that.value)); + break; + + default: + break; + } + + // that is emptied. + that.kind_ = symbol_kind::S_YYEMPTY; + } + +#if YY_CPLUSPLUS < 201103L + parser::stack_symbol_type& + parser::stack_symbol_type::operator= (const stack_symbol_type& that) + { + state = that.state; + switch (that.kind ()) + { + case symbol_kind::S_anim: // anim + value.copy< anim_ptr > (that.value); + break; + + case symbol_kind::S_animation: // animation + value.copy< animation_ptr > (that.value); + break; + + case symbol_kind::S_animtree: // animtree + value.copy< animtree_ptr > (that.value); + break; + + case symbol_kind::S_color: // color + value.copy< color_ptr > (that.value); + break; + + case symbol_kind::S_constant: // constant + value.copy< constant_ptr > (that.value); + break; + + case symbol_kind::S_define: // define + value.copy< define_ptr > (that.value); + break; + + case symbol_kind::S_empty_array: // empty_array + value.copy< empty_array_ptr > (that.value); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.copy< expr_arguments_ptr > (that.value); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.copy< expr_assign_ptr > (that.value); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.copy< expr_call_ptr > (that.value); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.copy< expr_call_type_ptr > (that.value); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.copy< expr_ptr > (that.value); + break; + + case symbol_kind::S_false: // false + value.copy< false_ptr > (that.value); + break; + + case symbol_kind::S_file: // file + value.copy< file_ptr > (that.value); + break; + + case symbol_kind::S_float: // float + value.copy< float_ptr > (that.value); + break; + + case symbol_kind::S_game: // game + value.copy< game_ptr > (that.value); + break; + + case symbol_kind::S_include: // include + value.copy< include_ptr > (that.value); + break; + + case symbol_kind::S_integer: // integer + value.copy< integer_ptr > (that.value); + break; + + case symbol_kind::S_istring: // istring + value.copy< istring_ptr > (that.value); + break; + + case symbol_kind::S_level: // level + value.copy< level_ptr > (that.value); + break; + + case symbol_kind::S_name: // name + value.copy< name_ptr > (that.value); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.copy< node_ptr > (that.value); + break; + + case symbol_kind::S_parameters: // parameters + value.copy< parameters_ptr > (that.value); + break; + + case symbol_kind::S_program: // program + value.copy< program_ptr > (that.value); + break; + + case symbol_kind::S_self: // self + value.copy< self_ptr > (that.value); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.copy< std::string > (that.value); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.copy< stmt_assign_ptr > (that.value); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.copy< stmt_break_ptr > (that.value); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.copy< stmt_call_ptr > (that.value); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.copy< stmt_case_ptr > (that.value); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.copy< stmt_continue_ptr > (that.value); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.copy< stmt_default_ptr > (that.value); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.copy< stmt_endon_ptr > (that.value); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.copy< stmt_for_ptr > (that.value); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.copy< stmt_foreach_ptr > (that.value); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.copy< stmt_if_ptr > (that.value); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.copy< stmt_ifelse_ptr > (that.value); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.copy< stmt_list_ptr > (that.value); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.copy< stmt_notify_ptr > (that.value); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.copy< stmt_ptr > (that.value); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.copy< stmt_return_ptr > (that.value); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.copy< stmt_switch_ptr > (that.value); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.copy< stmt_wait_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.copy< stmt_waitframe_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.copy< stmt_waittill_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.copy< stmt_waittillframeend_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.copy< stmt_waittillmatch_ptr > (that.value); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.copy< stmt_while_ptr > (that.value); + break; + + case symbol_kind::S_string: // string + value.copy< string_ptr > (that.value); + break; + + case symbol_kind::S_thisthread: // thisthread + value.copy< thisthread_ptr > (that.value); + break; + + case symbol_kind::S_thread: // thread + value.copy< thread_ptr > (that.value); + break; + + case symbol_kind::S_true: // true + value.copy< true_ptr > (that.value); + break; + + case symbol_kind::S_undefined: // undefined + value.copy< undefined_ptr > (that.value); + break; + + case symbol_kind::S_usingtree: // usingtree + value.copy< usingtree_ptr > (that.value); + break; + + case symbol_kind::S_vector: // vector + value.copy< vector_ptr > (that.value); + break; + + default: + break; + } + + location = that.location; + return *this; + } + + parser::stack_symbol_type& + parser::stack_symbol_type::operator= (stack_symbol_type& that) + { + state = that.state; + switch (that.kind ()) + { + case symbol_kind::S_anim: // anim + value.move< anim_ptr > (that.value); + break; + + case symbol_kind::S_animation: // animation + value.move< animation_ptr > (that.value); + break; + + case symbol_kind::S_animtree: // animtree + value.move< animtree_ptr > (that.value); + break; + + case symbol_kind::S_color: // color + value.move< color_ptr > (that.value); + break; + + case symbol_kind::S_constant: // constant + value.move< constant_ptr > (that.value); + break; + + case symbol_kind::S_define: // define + value.move< define_ptr > (that.value); + break; + + case symbol_kind::S_empty_array: // empty_array + value.move< empty_array_ptr > (that.value); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.move< expr_arguments_ptr > (that.value); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.move< expr_assign_ptr > (that.value); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.move< expr_call_ptr > (that.value); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.move< expr_call_type_ptr > (that.value); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.move< expr_ptr > (that.value); + break; + + case symbol_kind::S_false: // false + value.move< false_ptr > (that.value); + break; + + case symbol_kind::S_file: // file + value.move< file_ptr > (that.value); + break; + + case symbol_kind::S_float: // float + value.move< float_ptr > (that.value); + break; + + case symbol_kind::S_game: // game + value.move< game_ptr > (that.value); + break; + + case symbol_kind::S_include: // include + value.move< include_ptr > (that.value); + break; + + case symbol_kind::S_integer: // integer + value.move< integer_ptr > (that.value); + break; + + case symbol_kind::S_istring: // istring + value.move< istring_ptr > (that.value); + break; + + case symbol_kind::S_level: // level + value.move< level_ptr > (that.value); + break; + + case symbol_kind::S_name: // name + value.move< name_ptr > (that.value); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.move< node_ptr > (that.value); + break; + + case symbol_kind::S_parameters: // parameters + value.move< parameters_ptr > (that.value); + break; + + case symbol_kind::S_program: // program + value.move< program_ptr > (that.value); + break; + + case symbol_kind::S_self: // self + value.move< self_ptr > (that.value); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.move< std::string > (that.value); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< stmt_assign_ptr > (that.value); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< stmt_break_ptr > (that.value); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< stmt_call_ptr > (that.value); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< stmt_case_ptr > (that.value); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< stmt_continue_ptr > (that.value); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< stmt_default_ptr > (that.value); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< stmt_endon_ptr > (that.value); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< stmt_for_ptr > (that.value); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< stmt_foreach_ptr > (that.value); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< stmt_if_ptr > (that.value); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< stmt_ifelse_ptr > (that.value); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.move< stmt_list_ptr > (that.value); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< stmt_notify_ptr > (that.value); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.move< stmt_ptr > (that.value); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< stmt_return_ptr > (that.value); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< stmt_switch_ptr > (that.value); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< stmt_wait_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< stmt_waitframe_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< stmt_waittill_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< stmt_waittillframeend_ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< stmt_waittillmatch_ptr > (that.value); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< stmt_while_ptr > (that.value); + break; + + case symbol_kind::S_string: // string + value.move< string_ptr > (that.value); + break; + + case symbol_kind::S_thisthread: // thisthread + value.move< thisthread_ptr > (that.value); + break; + + case symbol_kind::S_thread: // thread + value.move< thread_ptr > (that.value); + break; + + case symbol_kind::S_true: // true + value.move< true_ptr > (that.value); + break; + + case symbol_kind::S_undefined: // undefined + value.move< undefined_ptr > (that.value); + break; + + case symbol_kind::S_usingtree: // usingtree + value.move< usingtree_ptr > (that.value); + break; + + case symbol_kind::S_vector: // vector + value.move< vector_ptr > (that.value); + break; + + default: + break; + } + + location = that.location; + // that is emptied. + that.state = empty_state; + return *this; + } +#endif + + template + void + parser::yy_destroy_ (const char* yymsg, basic_symbol& yysym) const + { + if (yymsg) + YY_SYMBOL_PRINT (yymsg, yysym); + } + +#if S4DEBUG + template + void + parser::yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const + { + std::ostream& yyoutput = yyo; + YY_USE (yyoutput); + if (yysym.empty ()) + yyo << "empty symbol"; + else + { + symbol_kind_type yykind = yysym.kind (); + yyo << (yykind < YYNTOKENS ? "token" : "nterm") + << ' ' << yysym.name () << " (" + << yysym.location << ": "; + YY_USE (yykind); + yyo << ')'; + } + } +#endif + + void + parser::yypush_ (const char* m, YY_MOVE_REF (stack_symbol_type) sym) + { + if (m) + YY_SYMBOL_PRINT (m, sym); + yystack_.push (YY_MOVE (sym)); + } + + void + parser::yypush_ (const char* m, state_type s, YY_MOVE_REF (symbol_type) sym) + { +#if 201103L <= YY_CPLUSPLUS + yypush_ (m, stack_symbol_type (s, std::move (sym))); +#else + stack_symbol_type ss (s, sym); + yypush_ (m, ss); +#endif + } + + void + parser::yypop_ (int n) + { + yystack_.pop (n); + } + +#if S4DEBUG + std::ostream& + parser::debug_stream () const + { + return *yycdebug_; + } + + void + parser::set_debug_stream (std::ostream& o) + { + yycdebug_ = &o; + } + + + parser::debug_level_type + parser::debug_level () const + { + return yydebug_; + } + + void + parser::set_debug_level (debug_level_type l) + { + yydebug_ = l; + } +#endif // S4DEBUG + + parser::state_type + parser::yy_lr_goto_state_ (state_type yystate, int yysym) + { + int yyr = yypgoto_[yysym - YYNTOKENS] + yystate; + if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate) + return yytable_[yyr]; + else + return yydefgoto_[yysym - YYNTOKENS]; + } + + bool + parser::yy_pact_value_is_default_ (int yyvalue) + { + return yyvalue == yypact_ninf_; + } + + bool + parser::yy_table_value_is_error_ (int yyvalue) + { + return yyvalue == yytable_ninf_; + } + + int + parser::operator() () + { + return parse (); + } + + int + parser::parse () + { + int yyn; + /// Length of the RHS of the rule being reduced. + int yylen = 0; + + // Error handling. + int yynerrs_ = 0; + int yyerrstatus_ = 0; + + /// The lookahead symbol. + symbol_type yyla; + + /// The locations where the error started and ended. + stack_symbol_type yyerror_range[3]; + + /// The return value of parse (). + int yyresult; + + /// Discard the LAC context in case there still is one left from a + /// previous invocation. + yy_lac_discard_ ("init"); + +#if YY_EXCEPTIONS + try +#endif // YY_EXCEPTIONS + { + YYCDEBUG << "Starting parse\n"; + + + /* Initialize the stack. The initial state will be set in + yynewstate, since the latter expects the semantical and the + location values to have been already stored, initialize these + stacks with a primary value. */ + yystack_.clear (); + yypush_ (YY_NULLPTR, 0, YY_MOVE (yyla)); + + /*-----------------------------------------------. + | yynewstate -- push a new symbol on the stack. | + `-----------------------------------------------*/ + yynewstate: + YYCDEBUG << "Entering state " << int (yystack_[0].state) << '\n'; + YY_STACK_PRINT (); + + // Accept? + if (yystack_[0].state == yyfinal_) + YYACCEPT; + + goto yybackup; + + + /*-----------. + | yybackup. | + `-----------*/ + yybackup: + // Try to take a decision without lookahead. + yyn = yypact_[+yystack_[0].state]; + if (yy_pact_value_is_default_ (yyn)) + goto yydefault; + + // Read a lookahead token. + if (yyla.empty ()) + { + YYCDEBUG << "Reading a token\n"; +#if YY_EXCEPTIONS + try +#endif // YY_EXCEPTIONS + { + symbol_type yylookahead (yylex (yyscanner, loc)); + yyla.move (yylookahead); + } +#if YY_EXCEPTIONS + catch (const syntax_error& yyexc) + { + YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; + error (yyexc); + goto yyerrlab1; + } +#endif // YY_EXCEPTIONS + } + YY_SYMBOL_PRINT ("Next token is", yyla); + + if (yyla.kind () == symbol_kind::S_YYerror) + { + // The scanner already issued an error message, process directly + // to error recovery. But do not keep the error token as + // lookahead, it is too special and may lead us to an endless + // loop in error recovery. */ + yyla.kind_ = symbol_kind::S_YYUNDEF; + goto yyerrlab1; + } + + /* If the proper action on seeing token YYLA.TYPE is to reduce or + to detect an error, take that action. */ + yyn += yyla.kind (); + if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.kind ()) + { + if (!yy_lac_establish_ (yyla.kind ())) + goto yyerrlab; + goto yydefault; + } + + // Reduce or error. + yyn = yytable_[yyn]; + if (yyn <= 0) + { + if (yy_table_value_is_error_ (yyn)) + goto yyerrlab; + if (!yy_lac_establish_ (yyla.kind ())) + goto yyerrlab; + + yyn = -yyn; + goto yyreduce; + } + + // Count tokens shifted since error; after three, turn off error status. + if (yyerrstatus_) + --yyerrstatus_; + + // Shift the lookahead token. + yypush_ ("Shifting", state_type (yyn), YY_MOVE (yyla)); + yy_lac_discard_ ("shift"); + goto yynewstate; + + + /*-----------------------------------------------------------. + | yydefault -- do the default action for the current state. | + `-----------------------------------------------------------*/ + yydefault: + yyn = yydefact_[+yystack_[0].state]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + + /*-----------------------------. + | yyreduce -- do a reduction. | + `-----------------------------*/ + yyreduce: + yylen = yyr2_[yyn]; + { + stack_symbol_type yylhs; + yylhs.state = yy_lr_goto_state_ (yystack_[yylen].state, yyr1_[yyn]); + /* Variants are always initialized to an empty instance of the + correct type. The default '$$ = $1' action is NOT applied + when using variants. */ + switch (yyr1_[yyn]) + { + case symbol_kind::S_anim: // anim + yylhs.value.emplace< anim_ptr > (); + break; + + case symbol_kind::S_animation: // animation + yylhs.value.emplace< animation_ptr > (); + break; + + case symbol_kind::S_animtree: // animtree + yylhs.value.emplace< animtree_ptr > (); + break; + + case symbol_kind::S_color: // color + yylhs.value.emplace< color_ptr > (); + break; + + case symbol_kind::S_constant: // constant + yylhs.value.emplace< constant_ptr > (); + break; + + case symbol_kind::S_define: // define + yylhs.value.emplace< define_ptr > (); + break; + + case symbol_kind::S_empty_array: // empty_array + yylhs.value.emplace< empty_array_ptr > (); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + yylhs.value.emplace< expr_arguments_ptr > (); + break; + + case symbol_kind::S_expr_assign: // expr_assign + yylhs.value.emplace< expr_assign_ptr > (); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + yylhs.value.emplace< expr_call_ptr > (); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + yylhs.value.emplace< expr_call_type_ptr > (); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + yylhs.value.emplace< expr_ptr > (); + break; + + case symbol_kind::S_false: // false + yylhs.value.emplace< false_ptr > (); + break; + + case symbol_kind::S_file: // file + yylhs.value.emplace< file_ptr > (); + break; + + case symbol_kind::S_float: // float + yylhs.value.emplace< float_ptr > (); + break; + + case symbol_kind::S_game: // game + yylhs.value.emplace< game_ptr > (); + break; + + case symbol_kind::S_include: // include + yylhs.value.emplace< include_ptr > (); + break; + + case symbol_kind::S_integer: // integer + yylhs.value.emplace< integer_ptr > (); + break; + + case symbol_kind::S_istring: // istring + yylhs.value.emplace< istring_ptr > (); + break; + + case symbol_kind::S_level: // level + yylhs.value.emplace< level_ptr > (); + break; + + case symbol_kind::S_name: // name + yylhs.value.emplace< name_ptr > (); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + yylhs.value.emplace< node_ptr > (); + break; + + case symbol_kind::S_parameters: // parameters + yylhs.value.emplace< parameters_ptr > (); + break; + + case symbol_kind::S_program: // program + yylhs.value.emplace< program_ptr > (); + break; + + case symbol_kind::S_self: // self + yylhs.value.emplace< self_ptr > (); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + yylhs.value.emplace< std::string > (); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + yylhs.value.emplace< stmt_assign_ptr > (); + break; + + case symbol_kind::S_stmt_break: // stmt_break + yylhs.value.emplace< stmt_break_ptr > (); + break; + + case symbol_kind::S_stmt_call: // stmt_call + yylhs.value.emplace< stmt_call_ptr > (); + break; + + case symbol_kind::S_stmt_case: // stmt_case + yylhs.value.emplace< stmt_case_ptr > (); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + yylhs.value.emplace< stmt_continue_ptr > (); + break; + + case symbol_kind::S_stmt_default: // stmt_default + yylhs.value.emplace< stmt_default_ptr > (); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + yylhs.value.emplace< stmt_endon_ptr > (); + break; + + case symbol_kind::S_stmt_for: // stmt_for + yylhs.value.emplace< stmt_for_ptr > (); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + yylhs.value.emplace< stmt_foreach_ptr > (); + break; + + case symbol_kind::S_stmt_if: // stmt_if + yylhs.value.emplace< stmt_if_ptr > (); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + yylhs.value.emplace< stmt_ifelse_ptr > (); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + yylhs.value.emplace< stmt_list_ptr > (); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + yylhs.value.emplace< stmt_notify_ptr > (); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + yylhs.value.emplace< stmt_ptr > (); + break; + + case symbol_kind::S_stmt_return: // stmt_return + yylhs.value.emplace< stmt_return_ptr > (); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + yylhs.value.emplace< stmt_switch_ptr > (); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + yylhs.value.emplace< stmt_wait_ptr > (); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + yylhs.value.emplace< stmt_waitframe_ptr > (); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + yylhs.value.emplace< stmt_waittill_ptr > (); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + yylhs.value.emplace< stmt_waittillframeend_ptr > (); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + yylhs.value.emplace< stmt_waittillmatch_ptr > (); + break; + + case symbol_kind::S_stmt_while: // stmt_while + yylhs.value.emplace< stmt_while_ptr > (); + break; + + case symbol_kind::S_string: // string + yylhs.value.emplace< string_ptr > (); + break; + + case symbol_kind::S_thisthread: // thisthread + yylhs.value.emplace< thisthread_ptr > (); + break; + + case symbol_kind::S_thread: // thread + yylhs.value.emplace< thread_ptr > (); + break; + + case symbol_kind::S_true: // true + yylhs.value.emplace< true_ptr > (); + break; + + case symbol_kind::S_undefined: // undefined + yylhs.value.emplace< undefined_ptr > (); + break; + + case symbol_kind::S_usingtree: // usingtree + yylhs.value.emplace< usingtree_ptr > (); + break; + + case symbol_kind::S_vector: // vector + yylhs.value.emplace< vector_ptr > (); + break; + + default: + break; + } + + + // Default location. + { + stack_type::slice range (yystack_, yylen); + YYLLOC_DEFAULT (yylhs.location, range, yylen); + yyerror_range[1].location = yylhs.location; + } + + // Perform the reduction. + YY_REDUCE_PRINT (yyn); +#if YY_EXCEPTIONS + try +#endif // YY_EXCEPTIONS + { + switch (yyn) + { + case 2: // root: program +#line 240 "parser.ypp" + { ast = std::move(yystack_[0].value.as < program_ptr > ()); } +#line 1786 "parser.cpp" + break; + + case 3: // root: %empty +#line 241 "parser.ypp" + { ast = std::make_unique(yylhs.location); } +#line 1792 "parser.cpp" + break; + + case 4: // program: program include +#line 246 "parser.ypp" + { yylhs.value.as < program_ptr > () = std::move(yystack_[1].value.as < program_ptr > ()); yylhs.value.as < program_ptr > ()->includes.push_back(std::move(yystack_[0].value.as < include_ptr > ())); } +#line 1798 "parser.cpp" + break; + + case 5: // program: program define +#line 248 "parser.ypp" + { yylhs.value.as < program_ptr > () = std::move(yystack_[1].value.as < program_ptr > ()); yylhs.value.as < program_ptr > ()->definitions.push_back(std::move(yystack_[0].value.as < define_ptr > ())); } +#line 1804 "parser.cpp" + break; + + case 6: // program: include +#line 250 "parser.ypp" + { yylhs.value.as < program_ptr > () = std::make_unique(yylhs.location); yylhs.value.as < program_ptr > ()->includes.push_back(std::move(yystack_[0].value.as < include_ptr > ())); } +#line 1810 "parser.cpp" + break; + + case 7: // program: define +#line 252 "parser.ypp" + { yylhs.value.as < program_ptr > () = std::make_unique(yylhs.location); yylhs.value.as < program_ptr > ()->definitions.push_back(std::move(yystack_[0].value.as < define_ptr > ())); } +#line 1816 "parser.cpp" + break; + + case 8: // include: "#include" file ";" +#line 257 "parser.ypp" + { yylhs.value.as < include_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < file_ptr > ())); } +#line 1822 "parser.cpp" + break; + + case 9: // define: usingtree +#line 261 "parser.ypp" + { yylhs.value.as < define_ptr > ().as_usingtree = std::move(yystack_[0].value.as < usingtree_ptr > ()); } +#line 1828 "parser.cpp" + break; + + case 10: // define: constant +#line 262 "parser.ypp" + { yylhs.value.as < define_ptr > ().as_constant = std::move(yystack_[0].value.as < constant_ptr > ()); } +#line 1834 "parser.cpp" + break; + + case 11: // define: thread +#line 263 "parser.ypp" + { yylhs.value.as < define_ptr > ().as_thread = std::move(yystack_[0].value.as < thread_ptr > ()); } +#line 1840 "parser.cpp" + break; + + case 12: // usingtree: "#using_animtree" "(" string ")" ";" +#line 268 "parser.ypp" + { yylhs.value.as < usingtree_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < string_ptr > ())); } +#line 1846 "parser.cpp" + break; + + case 13: // constant: name "=" expr ";" +#line 273 "parser.ypp" + { yylhs.value.as < constant_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[3].value.as < name_ptr > ()), std::move(yystack_[1].value.as < expr_ptr > ())); } +#line 1852 "parser.cpp" + break; + + case 14: // thread: name "(" parameters ")" stmt_block +#line 278 "parser.ypp" + { yylhs.value.as < thread_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < name_ptr > ()), std::move(yystack_[2].value.as < parameters_ptr > ()), std::move(yystack_[0].value.as < stmt_list_ptr > ())); } +#line 1858 "parser.cpp" + break; + + case 15: // parameters: parameters "," name +#line 283 "parser.ypp" + { yylhs.value.as < parameters_ptr > () = std::move(yystack_[2].value.as < parameters_ptr > ()); yylhs.value.as < parameters_ptr > ()->list.push_back(std::move(yystack_[0].value.as < name_ptr > ())); } +#line 1864 "parser.cpp" + break; + + case 16: // parameters: name +#line 285 "parser.ypp" + { yylhs.value.as < parameters_ptr > () = std::make_unique(yylhs.location); yylhs.value.as < parameters_ptr > ()->list.push_back(std::move(yystack_[0].value.as < name_ptr > ())); } +#line 1870 "parser.cpp" + break; + + case 17: // parameters: %empty +#line 287 "parser.ypp" + { yylhs.value.as < parameters_ptr > () = std::make_unique(yylhs.location); } +#line 1876 "parser.cpp" + break; + + case 18: // stmt: stmt_block +#line 291 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_list = std::move(yystack_[0].value.as < stmt_list_ptr > ()); } +#line 1882 "parser.cpp" + break; + + case 19: // stmt: stmt_call +#line 292 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_call = std::move(yystack_[0].value.as < stmt_call_ptr > ()); } +#line 1888 "parser.cpp" + break; + + case 20: // stmt: stmt_assign +#line 293 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_assign = std::move(yystack_[0].value.as < stmt_assign_ptr > ()); } +#line 1894 "parser.cpp" + break; + + case 21: // stmt: stmt_endon +#line 294 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_endon = std::move(yystack_[0].value.as < stmt_endon_ptr > ()); } +#line 1900 "parser.cpp" + break; + + case 22: // stmt: stmt_notify +#line 295 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_notify = std::move(yystack_[0].value.as < stmt_notify_ptr > ()); } +#line 1906 "parser.cpp" + break; + + case 23: // stmt: stmt_wait +#line 296 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_wait = std::move(yystack_[0].value.as < stmt_wait_ptr > ()); } +#line 1912 "parser.cpp" + break; + + case 24: // stmt: stmt_waittill +#line 297 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_waittill = std::move(yystack_[0].value.as < stmt_waittill_ptr > ()); } +#line 1918 "parser.cpp" + break; + + case 25: // stmt: stmt_waittillmatch +#line 298 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_waittillmatch = std::move(yystack_[0].value.as < stmt_waittillmatch_ptr > ()); } +#line 1924 "parser.cpp" + break; + + case 26: // stmt: stmt_waittillframeend +#line 299 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_waittillframeend = std::move(yystack_[0].value.as < stmt_waittillframeend_ptr > ()); } +#line 1930 "parser.cpp" + break; + + case 27: // stmt: stmt_waitframe +#line 300 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_waitframe = std::move(yystack_[0].value.as < stmt_waitframe_ptr > ()); } +#line 1936 "parser.cpp" + break; + + case 28: // stmt: stmt_if +#line 301 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_if = std::move(yystack_[0].value.as < stmt_if_ptr > ()); } +#line 1942 "parser.cpp" + break; + + case 29: // stmt: stmt_ifelse +#line 302 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_ifelse = std::move(yystack_[0].value.as < stmt_ifelse_ptr > ()); } +#line 1948 "parser.cpp" + break; + + case 30: // stmt: stmt_while +#line 303 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_while = std::move(yystack_[0].value.as < stmt_while_ptr > ()); } +#line 1954 "parser.cpp" + break; + + case 31: // stmt: stmt_for +#line 304 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_for = std::move(yystack_[0].value.as < stmt_for_ptr > ()); } +#line 1960 "parser.cpp" + break; + + case 32: // stmt: stmt_foreach +#line 305 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_foreach = std::move(yystack_[0].value.as < stmt_foreach_ptr > ()); } +#line 1966 "parser.cpp" + break; + + case 33: // stmt: stmt_switch +#line 306 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_switch = std::move(yystack_[0].value.as < stmt_switch_ptr > ()); } +#line 1972 "parser.cpp" + break; + + case 34: // stmt: stmt_case +#line 307 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_case = std::move(yystack_[0].value.as < stmt_case_ptr > ()); } +#line 1978 "parser.cpp" + break; + + case 35: // stmt: stmt_default +#line 308 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_default = std::move(yystack_[0].value.as < stmt_default_ptr > ()); } +#line 1984 "parser.cpp" + break; + + case 36: // stmt: stmt_break +#line 309 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_break = std::move(yystack_[0].value.as < stmt_break_ptr > ()); } +#line 1990 "parser.cpp" + break; + + case 37: // stmt: stmt_continue +#line 310 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_continue = std::move(yystack_[0].value.as < stmt_continue_ptr > ()); } +#line 1996 "parser.cpp" + break; + + case 38: // stmt: stmt_return +#line 311 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_return = std::move(yystack_[0].value.as < stmt_return_ptr > ()); } +#line 2002 "parser.cpp" + break; + + case 39: // stmt_block: "{" stmt_list "}" +#line 315 "parser.ypp" + { yylhs.value.as < stmt_list_ptr > () = std::move(yystack_[1].value.as < stmt_list_ptr > ()); } +#line 2008 "parser.cpp" + break; + + case 40: // stmt_block: "{" "}" +#line 316 "parser.ypp" + { yylhs.value.as < stmt_list_ptr > () = std::make_unique(yylhs.location); } +#line 2014 "parser.cpp" + break; + + case 41: // stmt_list: stmt_list stmt +#line 321 "parser.ypp" + { yylhs.value.as < stmt_list_ptr > () = std::move(yystack_[1].value.as < stmt_list_ptr > ()); yylhs.value.as < stmt_list_ptr > ()->stmts.push_back(std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2020 "parser.cpp" + break; + + case 42: // stmt_list: stmt +#line 323 "parser.ypp" + { yylhs.value.as < stmt_list_ptr > () = std::make_unique(yylhs.location); yylhs.value.as < stmt_list_ptr > ()->stmts.push_back(std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2026 "parser.cpp" + break; + + case 43: // stmt_call: expr_call ";" +#line 328 "parser.ypp" + { yylhs.value.as < stmt_call_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < expr_call_ptr > ())); } +#line 2032 "parser.cpp" + break; + + case 44: // stmt_call: expr_call_thread ";" +#line 330 "parser.ypp" + { yylhs.value.as < stmt_call_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < expr_call_ptr > ())); } +#line 2038 "parser.cpp" + break; + + case 45: // stmt_assign: expr_assign ";" +#line 335 "parser.ypp" + { yylhs.value.as < stmt_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < expr_assign_ptr > ())); } +#line 2044 "parser.cpp" + break; + + case 46: // stmt_endon: object "endon" "(" expr ")" ";" +#line 340 "parser.ypp" + { yylhs.value.as < stmt_endon_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < node_ptr > ()), std::move(yystack_[2].value.as < expr_ptr > ())); } +#line 2050 "parser.cpp" + break; + + case 47: // stmt_notify: object "notify" "(" expr "," expr_arguments ")" ";" +#line 345 "parser.ypp" + { yylhs.value.as < stmt_notify_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < node_ptr > ()), std::move(yystack_[4].value.as < expr_ptr > ()), std::move(yystack_[2].value.as < expr_arguments_ptr > ())); } +#line 2056 "parser.cpp" + break; + + case 48: // stmt_notify: object "notify" "(" expr ")" ";" +#line 347 "parser.ypp" + { yylhs.value.as < stmt_notify_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < node_ptr > ()), std::move(yystack_[2].value.as < expr_ptr > ()), std::make_unique(yylhs.location)); } +#line 2062 "parser.cpp" + break; + + case 49: // stmt_wait: "wait" expr ";" +#line 352 "parser.ypp" + { yylhs.value.as < stmt_wait_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < expr_ptr > ())); } +#line 2068 "parser.cpp" + break; + + case 50: // stmt_waittill: object "waittill" "(" expr "," expr_arguments ")" ";" +#line 357 "parser.ypp" + { yylhs.value.as < stmt_waittill_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < node_ptr > ()), std::move(yystack_[4].value.as < expr_ptr > ()), std::move(yystack_[2].value.as < expr_arguments_ptr > ())); } +#line 2074 "parser.cpp" + break; + + case 51: // stmt_waittill: object "waittill" "(" expr ")" ";" +#line 359 "parser.ypp" + { yylhs.value.as < stmt_waittill_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < node_ptr > ()), std::move(yystack_[2].value.as < expr_ptr > ()), std::make_unique(yylhs.location)); } +#line 2080 "parser.cpp" + break; + + case 52: // stmt_waittillmatch: object "waittillmatch" "(" expr "," expr_arguments ")" ";" +#line 364 "parser.ypp" + { yylhs.value.as < stmt_waittillmatch_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < node_ptr > ()), std::move(yystack_[4].value.as < expr_ptr > ()), std::move(yystack_[2].value.as < expr_arguments_ptr > ())); } +#line 2086 "parser.cpp" + break; + + case 53: // stmt_waittillmatch: object "waittillmatch" "(" expr ")" ";" +#line 366 "parser.ypp" + { yylhs.value.as < stmt_waittillmatch_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < node_ptr > ()), std::move(yystack_[2].value.as < expr_ptr > ()), std::make_unique(yylhs.location)); } +#line 2092 "parser.cpp" + break; + + case 54: // stmt_waittillframeend: "waittillframeend" ";" +#line 371 "parser.ypp" + { yylhs.value.as < stmt_waittillframeend_ptr > () = std::make_unique(yylhs.location); } +#line 2098 "parser.cpp" + break; + + case 55: // stmt_waitframe: "waitframe" ";" +#line 376 "parser.ypp" + { yylhs.value.as < stmt_waitframe_ptr > () = std::make_unique(yylhs.location); } +#line 2104 "parser.cpp" + break; + + case 56: // stmt_waitframe: "waitframe" "(" ")" ";" +#line 378 "parser.ypp" + { yylhs.value.as < stmt_waitframe_ptr > () = std::make_unique(yylhs.location); } +#line 2110 "parser.cpp" + break; + + case 57: // stmt_if: "if" "(" expr ")" stmt +#line 383 "parser.ypp" + { yylhs.value.as < stmt_if_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2116 "parser.cpp" + break; + + case 58: // stmt_ifelse: "if" "(" expr ")" stmt "else" stmt +#line 388 "parser.ypp" + { yylhs.value.as < stmt_ifelse_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < expr_ptr > ()), std::move(yystack_[2].value.as < stmt_ptr > ()), std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2122 "parser.cpp" + break; + + case 59: // stmt_while: "while" "(" expr ")" stmt +#line 393 "parser.ypp" + { yylhs.value.as < stmt_while_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2128 "parser.cpp" + break; + + case 60: // stmt_for: "for" "(" for_stmt ";" for_expr ";" for_stmt ")" stmt +#line 398 "parser.ypp" + { yylhs.value.as < stmt_for_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[6].value.as < stmt_ptr > ()), std::move(yystack_[4].value.as < expr_ptr > ()), std::move(yystack_[2].value.as < stmt_ptr > ()), std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2134 "parser.cpp" + break; + + case 61: // stmt_foreach: "foreach" "(" name "in" expr ")" stmt +#line 403 "parser.ypp" + { yylhs.value.as < stmt_foreach_ptr > () = std::make_unique(yylhs.location, expr_ptr(std::move(yystack_[4].value.as < name_ptr > ())), std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2140 "parser.cpp" + break; + + case 62: // stmt_foreach: "foreach" "(" name "," name "in" expr ")" stmt +#line 405 "parser.ypp" + { yylhs.value.as < stmt_foreach_ptr > () = std::make_unique(yylhs.location, expr_ptr(std::move(yystack_[6].value.as < name_ptr > ())), expr_ptr(std::move(yystack_[4].value.as < name_ptr > ())), std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < stmt_ptr > ())); } +#line 2146 "parser.cpp" + break; + + case 63: // stmt_switch: "switch" "(" expr ")" stmt_block +#line 410 "parser.ypp" + { yylhs.value.as < stmt_switch_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < stmt_list_ptr > ())); } +#line 2152 "parser.cpp" + break; + + case 64: // stmt_case: "case" integer ":" +#line 415 "parser.ypp" + { yylhs.value.as < stmt_case_ptr > () = std::make_unique(yylhs.location, expr_ptr(std::move(yystack_[1].value.as < integer_ptr > ())), std::make_unique(yylhs.location)); } +#line 2158 "parser.cpp" + break; + + case 65: // stmt_case: "case" string ":" +#line 417 "parser.ypp" + { yylhs.value.as < stmt_case_ptr > () = std::make_unique(yylhs.location, expr_ptr(std::move(yystack_[1].value.as < string_ptr > ())), std::make_unique(yylhs.location)); } +#line 2164 "parser.cpp" + break; + + case 66: // stmt_default: "default" ":" +#line 422 "parser.ypp" + { yylhs.value.as < stmt_default_ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2170 "parser.cpp" + break; + + case 67: // stmt_break: "break" ";" +#line 427 "parser.ypp" + { yylhs.value.as < stmt_break_ptr > () = std::make_unique(yylhs.location); } +#line 2176 "parser.cpp" + break; + + case 68: // stmt_continue: "continue" ";" +#line 432 "parser.ypp" + { yylhs.value.as < stmt_continue_ptr > () = std::make_unique(yylhs.location); } +#line 2182 "parser.cpp" + break; + + case 69: // stmt_return: "return" expr ";" +#line 437 "parser.ypp" + { yylhs.value.as < stmt_return_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < expr_ptr > ())); } +#line 2188 "parser.cpp" + break; + + case 70: // stmt_return: "return" ";" +#line 439 "parser.ypp" + { yylhs.value.as < stmt_return_ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2194 "parser.cpp" + break; + + case 71: // for_stmt: expr_assign +#line 443 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_list = std::make_unique(yylhs.location); yylhs.value.as < stmt_ptr > ().as_list->stmts.push_back(stmt_ptr(std::make_unique(yylhs.location, std::move(yystack_[0].value.as < expr_assign_ptr > ())))); } +#line 2200 "parser.cpp" + break; + + case 72: // for_stmt: %empty +#line 444 "parser.ypp" + { yylhs.value.as < stmt_ptr > ().as_node = std::make_unique(yylhs.location); } +#line 2206 "parser.cpp" + break; + + case 73: // for_expr: expr +#line 448 "parser.ypp" + { yylhs.value.as < expr_ptr > () = std::move(yystack_[0].value.as < expr_ptr > ()); } +#line 2212 "parser.cpp" + break; + + case 74: // for_expr: %empty +#line 449 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location); } +#line 2218 "parser.cpp" + break; + + case 75: // expr: expr_compare +#line 453 "parser.ypp" + { yylhs.value.as < expr_ptr > () = std::move(yystack_[0].value.as < expr_ptr > ()); } +#line 2224 "parser.cpp" + break; + + case 76: // expr: expr_ternary +#line 454 "parser.ypp" + { yylhs.value.as < expr_ptr > () = std::move(yystack_[0].value.as < expr_ptr > ()); } +#line 2230 "parser.cpp" + break; + + case 77: // expr: expr_binary +#line 455 "parser.ypp" + { yylhs.value.as < expr_ptr > () = std::move(yystack_[0].value.as < expr_ptr > ()); } +#line 2236 "parser.cpp" + break; + + case 78: // expr: expr_primitive +#line 456 "parser.ypp" + { yylhs.value.as < expr_ptr > () = std::move(yystack_[0].value.as < expr_ptr > ()); } +#line 2242 "parser.cpp" + break; + + case 79: // expr_assign: "++" object +#line 460 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < node_ptr > ())); } +#line 2248 "parser.cpp" + break; + + case 80: // expr_assign: "--" object +#line 461 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < node_ptr > ())); } +#line 2254 "parser.cpp" + break; + + case 81: // expr_assign: object "++" +#line 462 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < node_ptr > ())); } +#line 2260 "parser.cpp" + break; + + case 82: // expr_assign: object "--" +#line 463 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < node_ptr > ())); } +#line 2266 "parser.cpp" + break; + + case 83: // expr_assign: object "=" expr +#line 464 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2272 "parser.cpp" + break; + + case 84: // expr_assign: object "|=" expr +#line 465 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2278 "parser.cpp" + break; + + case 85: // expr_assign: object "&=" expr +#line 466 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2284 "parser.cpp" + break; + + case 86: // expr_assign: object "^=" expr +#line 467 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2290 "parser.cpp" + break; + + case 87: // expr_assign: object "<<=" expr +#line 468 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()),std::move( yystack_[0].value.as < expr_ptr > ())); } +#line 2296 "parser.cpp" + break; + + case 88: // expr_assign: object ">>=" expr +#line 469 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2302 "parser.cpp" + break; + + case 89: // expr_assign: object "+=" expr +#line 470 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2308 "parser.cpp" + break; + + case 90: // expr_assign: object "-=" expr +#line 471 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2314 "parser.cpp" + break; + + case 91: // expr_assign: object "*=" expr +#line 472 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2320 "parser.cpp" + break; + + case 92: // expr_assign: object "/=" expr +#line 473 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2326 "parser.cpp" + break; + + case 93: // expr_assign: object "%=" expr +#line 474 "parser.ypp" + { yylhs.value.as < expr_assign_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2332 "parser.cpp" + break; + + case 94: // expr_compare: expr "||" expr +#line 478 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2338 "parser.cpp" + break; + + case 95: // expr_compare: expr "&&" expr +#line 479 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2344 "parser.cpp" + break; + + case 96: // expr_compare: expr "==" expr +#line 480 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2350 "parser.cpp" + break; + + case 97: // expr_compare: expr "!=" expr +#line 481 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2356 "parser.cpp" + break; + + case 98: // expr_compare: expr "<=" expr +#line 482 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2362 "parser.cpp" + break; + + case 99: // expr_compare: expr ">=" expr +#line 483 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2368 "parser.cpp" + break; + + case 100: // expr_compare: expr "<" expr +#line 484 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2374 "parser.cpp" + break; + + case 101: // expr_compare: expr ">" expr +#line 485 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2380 "parser.cpp" + break; + + case 102: // expr_ternary: expr "?" expr ":" expr +#line 489 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < expr_ptr > ()), std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2386 "parser.cpp" + break; + + case 103: // expr_binary: expr "|" expr +#line 493 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2392 "parser.cpp" + break; + + case 104: // expr_binary: expr "&" expr +#line 494 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2398 "parser.cpp" + break; + + case 105: // expr_binary: expr "^" expr +#line 495 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2404 "parser.cpp" + break; + + case 106: // expr_binary: expr "<<" expr +#line 496 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2410 "parser.cpp" + break; + + case 107: // expr_binary: expr ">>" expr +#line 497 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2416 "parser.cpp" + break; + + case 108: // expr_binary: expr "+" expr +#line 498 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2422 "parser.cpp" + break; + + case 109: // expr_binary: expr "-" expr +#line 499 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2428 "parser.cpp" + break; + + case 110: // expr_binary: expr "*" expr +#line 500 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2434 "parser.cpp" + break; + + case 111: // expr_binary: expr "/" expr +#line 501 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2440 "parser.cpp" + break; + + case 112: // expr_binary: expr "%" expr +#line 502 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < expr_ptr > ()), std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2446 "parser.cpp" + break; + + case 113: // expr_primitive: "(" expr ")" +#line 506 "parser.ypp" + { yylhs.value.as < expr_ptr > () = std::move(yystack_[1].value.as < expr_ptr > ()); } +#line 2452 "parser.cpp" + break; + + case 114: // expr_primitive: "~" expr +#line 507 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2458 "parser.cpp" + break; + + case 115: // expr_primitive: "!" expr +#line 508 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2464 "parser.cpp" + break; + + case 116: // expr_primitive: expr_call +#line 509 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < expr_call_ptr > ()); } +#line 2470 "parser.cpp" + break; + + case 117: // expr_primitive: expr_call_thread +#line 510 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < expr_call_ptr > ()); } +#line 2476 "parser.cpp" + break; + + case 118: // expr_primitive: expr_call_childthread +#line 511 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < expr_call_ptr > ()); } +#line 2482 "parser.cpp" + break; + + case 119: // expr_primitive: expr_function +#line 512 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < node_ptr > ()); } +#line 2488 "parser.cpp" + break; + + case 120: // expr_primitive: expr_add_array +#line 513 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < node_ptr > ()); } +#line 2494 "parser.cpp" + break; + + case 121: // expr_primitive: expr_array +#line 514 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < node_ptr > ()); } +#line 2500 "parser.cpp" + break; + + case 122: // expr_primitive: expr_field +#line 515 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < node_ptr > ()); } +#line 2506 "parser.cpp" + break; + + case 123: // expr_primitive: expr_size +#line 516 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < node_ptr > ()); } +#line 2512 "parser.cpp" + break; + + case 124: // expr_primitive: thisthread +#line 517 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < thisthread_ptr > ()); } +#line 2518 "parser.cpp" + break; + + case 125: // expr_primitive: empty_array +#line 518 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < empty_array_ptr > ()); } +#line 2524 "parser.cpp" + break; + + case 126: // expr_primitive: undefined +#line 519 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < undefined_ptr > ()); } +#line 2530 "parser.cpp" + break; + + case 127: // expr_primitive: game +#line 520 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < game_ptr > ()); } +#line 2536 "parser.cpp" + break; + + case 128: // expr_primitive: self +#line 521 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < self_ptr > ()); } +#line 2542 "parser.cpp" + break; + + case 129: // expr_primitive: anim +#line 522 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < anim_ptr > ()); } +#line 2548 "parser.cpp" + break; + + case 130: // expr_primitive: level +#line 523 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < level_ptr > ()); } +#line 2554 "parser.cpp" + break; + + case 131: // expr_primitive: animation +#line 524 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < animation_ptr > ()); } +#line 2560 "parser.cpp" + break; + + case 132: // expr_primitive: animtree +#line 525 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < animtree_ptr > ()); } +#line 2566 "parser.cpp" + break; + + case 133: // expr_primitive: name +#line 526 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < name_ptr > ()); } +#line 2572 "parser.cpp" + break; + + case 134: // expr_primitive: istring +#line 527 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < istring_ptr > ()); } +#line 2578 "parser.cpp" + break; + + case 135: // expr_primitive: string +#line 528 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < string_ptr > ()); } +#line 2584 "parser.cpp" + break; + + case 136: // expr_primitive: color +#line 529 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < color_ptr > ()); } +#line 2590 "parser.cpp" + break; + + case 137: // expr_primitive: vector +#line 530 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < vector_ptr > ()); } +#line 2596 "parser.cpp" + break; + + case 138: // expr_primitive: float +#line 531 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < float_ptr > ()); } +#line 2602 "parser.cpp" + break; + + case 139: // expr_primitive: integer +#line 532 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < integer_ptr > ()); } +#line 2608 "parser.cpp" + break; + + case 140: // expr_primitive: false +#line 533 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < false_ptr > ()); } +#line 2614 "parser.cpp" + break; + + case 141: // expr_primitive: true +#line 534 "parser.ypp" + { yylhs.value.as < expr_ptr > ().as_node = std::move(yystack_[0].value.as < true_ptr > ()); } +#line 2620 "parser.cpp" + break; + + case 142: // expr_call: expr_call_function +#line 538 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, false, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2626 "parser.cpp" + break; + + case 143: // expr_call: expr_call_pointer +#line 539 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, false, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2632 "parser.cpp" + break; + + case 144: // expr_call: object expr_call_function +#line 540 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, false, std::move(yystack_[1].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2638 "parser.cpp" + break; + + case 145: // expr_call: object expr_call_pointer +#line 541 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, false, std::move(yystack_[1].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2644 "parser.cpp" + break; + + case 146: // expr_call_thread: "thread" expr_call_function +#line 545 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, true, false, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2650 "parser.cpp" + break; + + case 147: // expr_call_thread: "thread" expr_call_pointer +#line 546 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, true, false, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2656 "parser.cpp" + break; + + case 148: // expr_call_thread: object "thread" expr_call_function +#line 547 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, true, false, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2662 "parser.cpp" + break; + + case 149: // expr_call_thread: object "thread" expr_call_pointer +#line 548 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, true, false, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2668 "parser.cpp" + break; + + case 150: // expr_call_childthread: "childthread" expr_call_function +#line 552 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, true, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2674 "parser.cpp" + break; + + case 151: // expr_call_childthread: "childthread" expr_call_pointer +#line 553 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, true, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2680 "parser.cpp" + break; + + case 152: // expr_call_childthread: object "childthread" expr_call_function +#line 554 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, true, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2686 "parser.cpp" + break; + + case 153: // expr_call_childthread: object "childthread" expr_call_pointer +#line 555 "parser.ypp" + { yylhs.value.as < expr_call_ptr > () = std::make_unique(yylhs.location, false, true, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < expr_call_type_ptr > ())); } +#line 2692 "parser.cpp" + break; + + case 154: // expr_call_function: name "(" expr_arguments ")" +#line 560 "parser.ypp" + {yylhs.value.as < expr_call_type_ptr > ().as_func = std::make_unique(yylhs.location, std::make_unique(), std::move(yystack_[3].value.as < name_ptr > ()), std::move(yystack_[1].value.as < expr_arguments_ptr > ())); } +#line 2698 "parser.cpp" + break; + + case 155: // expr_call_function: file "::" name "(" expr_arguments ")" +#line 562 "parser.ypp" + { yylhs.value.as < expr_call_type_ptr > ().as_func = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < file_ptr > ()), std::move(yystack_[3].value.as < name_ptr > ()), std::move(yystack_[1].value.as < expr_arguments_ptr > ())); } +#line 2704 "parser.cpp" + break; + + case 156: // expr_call_pointer: "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 567 "parser.ypp" + { yylhs.value.as < expr_call_type_ptr > ().as_pointer = std::make_unique(yylhs.location, false, std::move(yystack_[5].value.as < expr_ptr > ()), std::move(yystack_[1].value.as < expr_arguments_ptr > ())); } +#line 2710 "parser.cpp" + break; + + case 157: // expr_call_pointer: "call" "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 569 "parser.ypp" + { yylhs.value.as < expr_call_type_ptr > ().as_pointer = std::make_unique(yylhs.location, true, std::move(yystack_[5].value.as < expr_ptr > ()), std::move(yystack_[1].value.as < expr_arguments_ptr > ())); } +#line 2716 "parser.cpp" + break; + + case 158: // expr_arguments: expr_arguments_filled +#line 573 "parser.ypp" + { yylhs.value.as < expr_arguments_ptr > () = std::move(yystack_[0].value.as < expr_arguments_ptr > ()); } +#line 2722 "parser.cpp" + break; + + case 159: // expr_arguments: expr_arguments_empty +#line 574 "parser.ypp" + { yylhs.value.as < expr_arguments_ptr > () = std::move(yystack_[0].value.as < expr_arguments_ptr > ()); } +#line 2728 "parser.cpp" + break; + + case 160: // expr_arguments_filled: expr_arguments "," expr +#line 579 "parser.ypp" + { yylhs.value.as < expr_arguments_ptr > () = std::move(yystack_[2].value.as < expr_arguments_ptr > ()); yylhs.value.as < expr_arguments_ptr > ()->list.push_back(std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2734 "parser.cpp" + break; + + case 161: // expr_arguments_filled: expr +#line 581 "parser.ypp" + { yylhs.value.as < expr_arguments_ptr > () = std::make_unique(yylhs.location); yylhs.value.as < expr_arguments_ptr > ()->list.push_back(std::move(yystack_[0].value.as < expr_ptr > ())); } +#line 2740 "parser.cpp" + break; + + case 162: // expr_arguments_empty: %empty +#line 586 "parser.ypp" + { yylhs.value.as < expr_arguments_ptr > () = std::make_unique(yylhs.location); } +#line 2746 "parser.cpp" + break; + + case 163: // expr_function: "::" name +#line 591 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < name_ptr > ())); } +#line 2752 "parser.cpp" + break; + + case 164: // expr_function: file "::" name +#line 593 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < file_ptr > ()), std::move(yystack_[0].value.as < name_ptr > ())); } +#line 2758 "parser.cpp" + break; + + case 165: // expr_add_array: "[" expr_arguments_filled "]" +#line 598 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < expr_arguments_ptr > ())); } +#line 2764 "parser.cpp" + break; + + case 166: // expr_array: object "[" expr "]" +#line 603 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[3].value.as < node_ptr > ()), std::move(yystack_[1].value.as < expr_ptr > ())); } +#line 2770 "parser.cpp" + break; + + case 167: // expr_field: object "." name +#line 608 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ()), std::move(yystack_[0].value.as < name_ptr > ())); } +#line 2776 "parser.cpp" + break; + + case 168: // expr_size: object "." "size" +#line 613 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < node_ptr > ())); } +#line 2782 "parser.cpp" + break; + + case 169: // object: expr_call +#line 617 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < expr_call_ptr > ()); } +#line 2788 "parser.cpp" + break; + + case 170: // object: expr_array +#line 618 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < node_ptr > ()); } +#line 2794 "parser.cpp" + break; + + case 171: // object: expr_field +#line 619 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < node_ptr > ()); } +#line 2800 "parser.cpp" + break; + + case 172: // object: game +#line 620 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < game_ptr > ()); } +#line 2806 "parser.cpp" + break; + + case 173: // object: self +#line 621 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < self_ptr > ()); } +#line 2812 "parser.cpp" + break; + + case 174: // object: anim +#line 622 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < anim_ptr > ()); } +#line 2818 "parser.cpp" + break; + + case 175: // object: level +#line 623 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < level_ptr > ()); } +#line 2824 "parser.cpp" + break; + + case 176: // object: name +#line 624 "parser.ypp" + { yylhs.value.as < node_ptr > () = std::move(yystack_[0].value.as < name_ptr > ()); } +#line 2830 "parser.cpp" + break; + + case 177: // float: "-" "float" +#line 628 "parser.ypp" + { yylhs.value.as < float_ptr > () = std::make_unique(yylhs.location, "-" + yystack_[0].value.as < std::string > ()); } +#line 2836 "parser.cpp" + break; + + case 178: // float: "float" +#line 629 "parser.ypp" + { yylhs.value.as < float_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2842 "parser.cpp" + break; + + case 179: // integer: "-" "int" +#line 633 "parser.ypp" + { yylhs.value.as < integer_ptr > () = std::make_unique(yylhs.location, "-" + yystack_[0].value.as < std::string > ()); } +#line 2848 "parser.cpp" + break; + + case 180: // integer: "int" +#line 634 "parser.ypp" + { yylhs.value.as < integer_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2854 "parser.cpp" + break; + + case 181: // integer: "octal int" +#line 635 "parser.ypp" + { yylhs.value.as < integer_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2860 "parser.cpp" + break; + + case 182: // integer: "binary int" +#line 636 "parser.ypp" + { yylhs.value.as < integer_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2866 "parser.cpp" + break; + + case 183: // integer: "hexadecimal int" +#line 637 "parser.ypp" + { yylhs.value.as < integer_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2872 "parser.cpp" + break; + + case 184: // thisthread: "thisthread" +#line 640 "parser.ypp" + { yylhs.value.as < thisthread_ptr > () = std::make_unique(yylhs.location); } +#line 2878 "parser.cpp" + break; + + case 185: // empty_array: "[" "]" +#line 641 "parser.ypp" + { yylhs.value.as < empty_array_ptr > () = std::make_unique(yylhs.location); } +#line 2884 "parser.cpp" + break; + + case 186: // undefined: "undefined" +#line 642 "parser.ypp" + { yylhs.value.as < undefined_ptr > () = std::make_unique(yylhs.location); } +#line 2890 "parser.cpp" + break; + + case 187: // game: "game" +#line 643 "parser.ypp" + { yylhs.value.as < game_ptr > () = std::make_unique(yylhs.location); } +#line 2896 "parser.cpp" + break; + + case 188: // self: "self" +#line 644 "parser.ypp" + { yylhs.value.as < self_ptr > () = std::make_unique(yylhs.location); } +#line 2902 "parser.cpp" + break; + + case 189: // anim: "anim" +#line 645 "parser.ypp" + { yylhs.value.as < anim_ptr > () = std::make_unique(yylhs.location); } +#line 2908 "parser.cpp" + break; + + case 190: // level: "level" +#line 646 "parser.ypp" + { yylhs.value.as < level_ptr > () = std::make_unique(yylhs.location); } +#line 2914 "parser.cpp" + break; + + case 191: // animation: "%" "identifier" +#line 647 "parser.ypp" + { yylhs.value.as < animation_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2920 "parser.cpp" + break; + + case 192: // animtree: "#animtree" +#line 648 "parser.ypp" + { yylhs.value.as < animtree_ptr > () = std::make_unique(yylhs.location); } +#line 2926 "parser.cpp" + break; + + case 193: // name: "identifier" +#line 649 "parser.ypp" + { yylhs.value.as < name_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2932 "parser.cpp" + break; + + case 194: // file: "file path" +#line 650 "parser.ypp" + { yylhs.value.as < file_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2938 "parser.cpp" + break; + + case 195: // istring: "localized string" +#line 651 "parser.ypp" + { yylhs.value.as < istring_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2944 "parser.cpp" + break; + + case 196: // string: "string literal" +#line 652 "parser.ypp" + { yylhs.value.as < string_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2950 "parser.cpp" + break; + + case 197: // color: "color" +#line 653 "parser.ypp" + { yylhs.value.as < color_ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 2956 "parser.cpp" + break; + + case 198: // vector: "(" expr "," expr "," expr ")" +#line 654 "parser.ypp" + { yylhs.value.as < vector_ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < expr_ptr > ()), std::move(yystack_[3].value.as < expr_ptr > ()), std::move(yystack_[1].value.as < expr_ptr > ())); } +#line 2962 "parser.cpp" + break; + + case 199: // false: "false" +#line 655 "parser.ypp" + { yylhs.value.as < false_ptr > () = std::make_unique(yylhs.location); } +#line 2968 "parser.cpp" + break; + + case 200: // true: "true" +#line 656 "parser.ypp" + { yylhs.value.as < true_ptr > () = std::make_unique(yylhs.location); } +#line 2974 "parser.cpp" + break; + + +#line 2978 "parser.cpp" + + default: + break; + } + } +#if YY_EXCEPTIONS + catch (const syntax_error& yyexc) + { + YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; + error (yyexc); + YYERROR; + } +#endif // YY_EXCEPTIONS + YY_SYMBOL_PRINT ("-> $$ =", yylhs); + yypop_ (yylen); + yylen = 0; + + // Shift the result of the reduction. + yypush_ (YY_NULLPTR, YY_MOVE (yylhs)); + } + goto yynewstate; + + + /*--------------------------------------. + | yyerrlab -- here on detecting error. | + `--------------------------------------*/ + yyerrlab: + // If not already recovering from an error, report this error. + if (!yyerrstatus_) + { + ++yynerrs_; + context yyctx (*this, yyla); + std::string msg = yysyntax_error_ (yyctx); + error (yyla.location, YY_MOVE (msg)); + } + + + yyerror_range[1].location = yyla.location; + if (yyerrstatus_ == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + // Return failure if at end of input. + if (yyla.kind () == symbol_kind::S_YYEOF) + YYABORT; + else if (!yyla.empty ()) + { + yy_destroy_ ("Error: discarding", yyla); + yyla.clear (); + } + } + + // Else will try to reuse lookahead token after shifting the error token. + goto yyerrlab1; + + + /*---------------------------------------------------. + | yyerrorlab -- error raised explicitly by YYERROR. | + `---------------------------------------------------*/ + yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and + the label yyerrorlab therefore never appears in user code. */ + if (false) + YYERROR; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + yypop_ (yylen); + yylen = 0; + YY_STACK_PRINT (); + goto yyerrlab1; + + + /*-------------------------------------------------------------. + | yyerrlab1 -- common code for both syntax error and YYERROR. | + `-------------------------------------------------------------*/ + yyerrlab1: + yyerrstatus_ = 3; // Each real token shifted decrements this. + // Pop stack until we find a state that shifts the error token. + for (;;) + { + yyn = yypact_[+yystack_[0].state]; + if (!yy_pact_value_is_default_ (yyn)) + { + yyn += symbol_kind::S_YYerror; + if (0 <= yyn && yyn <= yylast_ + && yycheck_[yyn] == symbol_kind::S_YYerror) + { + yyn = yytable_[yyn]; + if (0 < yyn) + break; + } + } + + // Pop the current state because it cannot handle the error token. + if (yystack_.size () == 1) + YYABORT; + + yyerror_range[1].location = yystack_[0].location; + yy_destroy_ ("Error: popping", yystack_[0]); + yypop_ (); + YY_STACK_PRINT (); + } + { + stack_symbol_type error_token; + + yyerror_range[2].location = yyla.location; + YYLLOC_DEFAULT (error_token.location, yyerror_range, 2); + + // Shift the error token. + yy_lac_discard_ ("error recovery"); + error_token.state = state_type (yyn); + yypush_ ("Shifting", YY_MOVE (error_token)); + } + goto yynewstate; + + + /*-------------------------------------. + | yyacceptlab -- YYACCEPT comes here. | + `-------------------------------------*/ + yyacceptlab: + yyresult = 0; + goto yyreturn; + + + /*-----------------------------------. + | yyabortlab -- YYABORT comes here. | + `-----------------------------------*/ + yyabortlab: + yyresult = 1; + goto yyreturn; + + + /*-----------------------------------------------------. + | yyreturn -- parsing is finished, return the result. | + `-----------------------------------------------------*/ + yyreturn: + if (!yyla.empty ()) + yy_destroy_ ("Cleanup: discarding lookahead", yyla); + + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + yypop_ (yylen); + YY_STACK_PRINT (); + while (1 < yystack_.size ()) + { + yy_destroy_ ("Cleanup: popping", yystack_[0]); + yypop_ (); + } + + return yyresult; + } +#if YY_EXCEPTIONS + catch (...) + { + YYCDEBUG << "Exception caught: cleaning lookahead and stack\n"; + // Do not try to display the values of the reclaimed symbols, + // as their printers might throw an exception. + if (!yyla.empty ()) + yy_destroy_ (YY_NULLPTR, yyla); + + while (1 < yystack_.size ()) + { + yy_destroy_ (YY_NULLPTR, yystack_[0]); + yypop_ (); + } + throw; + } +#endif // YY_EXCEPTIONS + } + + void + parser::error (const syntax_error& yyexc) + { + error (yyexc.location, yyexc.what ()); + } + + const char * + parser::symbol_name (symbol_kind_type yysymbol) + { + static const char *const yy_sname[] = + { + "end of file", "error", "invalid token", "#include", "#using_animtree", + "#animtree", "endon", "notify", "wait", "waittill", "waittillmatch", + "waittillframeend", "waitframe", "if", "else", "while", "for", "foreach", + "in", "switch", "case", "default", "break", "continue", "return", + "thread", "childthread", "thisthread", "call", "true", "false", + "undefined", "size", "game", "self", "anim", "level", "(", ")", "{", "}", + "[", "]", ",", ".", "::", ":", ";", "?", "++", "--", "<<", ">>", "||", + "&&", "==", "!=", "<=", ">=", "<", ">", "!", "~", "=", "+=", "-=", "*=", + "/=", "%=", "|=", "&=", "^=", ">>=", "<<=", "|", "&", "^", "+", "-", "*", + "/", "%", "file path", "identifier", "string literal", + "localized string", "color", "float", "int", "octal int", "binary int", + "hexadecimal int", "ADD_ARRAY", "THEN", "TERN", "NEG", "ANIMREF", + "PREINC", "PREDEC", "POSTINC", "POSTDEC", "$accept", "root", "program", + "include", "define", "usingtree", "constant", "thread", "parameters", + "stmt", "stmt_block", "stmt_list", "stmt_call", "stmt_assign", + "stmt_endon", "stmt_notify", "stmt_wait", "stmt_waittill", + "stmt_waittillmatch", "stmt_waittillframeend", "stmt_waitframe", + "stmt_if", "stmt_ifelse", "stmt_while", "stmt_for", "stmt_foreach", + "stmt_switch", "stmt_case", "stmt_default", "stmt_break", + "stmt_continue", "stmt_return", "for_stmt", "for_expr", "expr", + "expr_assign", "expr_compare", "expr_ternary", "expr_binary", + "expr_primitive", "expr_call", "expr_call_thread", + "expr_call_childthread", "expr_call_function", "expr_call_pointer", + "expr_arguments", "expr_arguments_filled", "expr_arguments_empty", + "expr_function", "expr_add_array", "expr_array", "expr_field", + "expr_size", "object", "float", "integer", "thisthread", "empty_array", + "undefined", "game", "self", "anim", "level", "animation", "animtree", + "name", "file", "istring", "string", "color", "vector", "false", "true", YY_NULLPTR + }; + return yy_sname[yysymbol]; + } + + + + // parser::context. + parser::context::context (const parser& yyparser, const symbol_type& yyla) + : yyparser_ (yyparser) + , yyla_ (yyla) + {} + + int + parser::context::expected_tokens (symbol_kind_type yyarg[], int yyargn) const + { + // Actual number of expected tokens + int yycount = 0; + +#if S4DEBUG + // Execute LAC once. We don't care if it is successful, we + // only do it for the sake of debugging output. + if (!yyparser_.yy_lac_established_) + yyparser_.yy_lac_check_ (yyla_.kind ()); +#endif + + for (int yyx = 0; yyx < YYNTOKENS; ++yyx) + { + symbol_kind_type yysym = YY_CAST (symbol_kind_type, yyx); + if (yysym != symbol_kind::S_YYerror + && yysym != symbol_kind::S_YYUNDEF + && yyparser_.yy_lac_check_ (yysym)) + { + if (!yyarg) + ++yycount; + else if (yycount == yyargn) + return 0; + else + yyarg[yycount++] = yysym; + } + } + if (yyarg && yycount == 0 && 0 < yyargn) + yyarg[0] = symbol_kind::S_YYEMPTY; + return yycount; + } + + + bool + parser::yy_lac_check_ (symbol_kind_type yytoken) const + { + // Logically, the yylac_stack's lifetime is confined to this function. + // Clear it, to get rid of potential left-overs from previous call. + yylac_stack_.clear (); + // Reduce until we encounter a shift and thereby accept the token. +#if S4DEBUG + YYCDEBUG << "LAC: checking lookahead " << symbol_name (yytoken) << ':'; +#endif + std::ptrdiff_t lac_top = 0; + while (true) + { + state_type top_state = (yylac_stack_.empty () + ? yystack_[lac_top].state + : yylac_stack_.back ()); + int yyrule = yypact_[+top_state]; + if (yy_pact_value_is_default_ (yyrule) + || (yyrule += yytoken) < 0 || yylast_ < yyrule + || yycheck_[yyrule] != yytoken) + { + // Use the default action. + yyrule = yydefact_[+top_state]; + if (yyrule == 0) + { + YYCDEBUG << " Err\n"; + return false; + } + } + else + { + // Use the action from yytable. + yyrule = yytable_[yyrule]; + if (yy_table_value_is_error_ (yyrule)) + { + YYCDEBUG << " Err\n"; + return false; + } + if (0 < yyrule) + { + YYCDEBUG << " S" << yyrule << '\n'; + return true; + } + yyrule = -yyrule; + } + // By now we know we have to simulate a reduce. + YYCDEBUG << " R" << yyrule - 1; + // Pop the corresponding number of values from the stack. + { + std::ptrdiff_t yylen = yyr2_[yyrule]; + // First pop from the LAC stack as many tokens as possible. + std::ptrdiff_t lac_size = std::ptrdiff_t (yylac_stack_.size ()); + if (yylen < lac_size) + { + yylac_stack_.resize (std::size_t (lac_size - yylen)); + yylen = 0; + } + else if (lac_size) + { + yylac_stack_.clear (); + yylen -= lac_size; + } + // Only afterwards look at the main stack. + // We simulate popping elements by incrementing lac_top. + lac_top += yylen; + } + // Keep top_state in sync with the updated stack. + top_state = (yylac_stack_.empty () + ? yystack_[lac_top].state + : yylac_stack_.back ()); + // Push the resulting state of the reduction. + state_type state = yy_lr_goto_state_ (top_state, yyr1_[yyrule]); + YYCDEBUG << " G" << int (state); + yylac_stack_.push_back (state); + } + } + + // Establish the initial context if no initial context currently exists. + bool + parser::yy_lac_establish_ (symbol_kind_type yytoken) + { + /* Establish the initial context for the current lookahead if no initial + context is currently established. + + We define a context as a snapshot of the parser stacks. We define + the initial context for a lookahead as the context in which the + parser initially examines that lookahead in order to select a + syntactic action. Thus, if the lookahead eventually proves + syntactically unacceptable (possibly in a later context reached via a + series of reductions), the initial context can be used to determine + the exact set of tokens that would be syntactically acceptable in the + lookahead's place. Moreover, it is the context after which any + further semantic actions would be erroneous because they would be + determined by a syntactically unacceptable token. + + yy_lac_establish_ should be invoked when a reduction is about to be + performed in an inconsistent state (which, for the purposes of LAC, + includes consistent states that don't know they're consistent because + their default reductions have been disabled). + + For parse.lac=full, the implementation of yy_lac_establish_ is as + follows. If no initial context is currently established for the + current lookahead, then check if that lookahead can eventually be + shifted if syntactic actions continue from the current context. */ + if (!yy_lac_established_) + { +#if S4DEBUG + YYCDEBUG << "LAC: initial context established for " + << symbol_name (yytoken) << '\n'; +#endif + yy_lac_established_ = true; + return yy_lac_check_ (yytoken); + } + return true; + } + + // Discard any previous initial lookahead context. + void + parser::yy_lac_discard_ (const char* evt) + { + /* Discard any previous initial lookahead context because of Event, + which may be a lookahead change or an invalidation of the currently + established initial context for the current lookahead. + + The most common example of a lookahead change is a shift. An example + of both cases is syntax error recovery. That is, a syntax error + occurs when the lookahead is syntactically erroneous for the + currently established initial context, so error recovery manipulates + the parser stacks to try to find a new initial context in which the + current lookahead is syntactically acceptable. If it fails to find + such a context, it discards the lookahead. */ + if (yy_lac_established_) + { + YYCDEBUG << "LAC: initial context discarded due to " + << evt << '\n'; + yy_lac_established_ = false; + } + } + + int + parser::yy_syntax_error_arguments_ (const context& yyctx, + symbol_kind_type yyarg[], int yyargn) const + { + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yyla) is + if this state is a consistent state with a default action. + Thus, detecting the absence of a lookahead is sufficient to + determine that there is no unexpected or expected token to + report. In that case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is + a consistent state with a default action. There might have + been a previous inconsistent state, consistent state with a + non-default action, or user semantic action that manipulated + yyla. (However, yyla is currently not documented for users.) + In the first two cases, it might appear that the current syntax + error should have been detected in the previous state when + yy_lac_check was invoked. However, at that time, there might + have been a different syntax error that discarded a different + initial context during error recovery, leaving behind the + current lookahead. + */ + + if (!yyctx.lookahead ().empty ()) + { + if (yyarg) + yyarg[0] = yyctx.token (); + int yyn = yyctx.expected_tokens (yyarg ? yyarg + 1 : yyarg, yyargn - 1); + return yyn + 1; + } + return 0; + } + + // Generate an error message. + std::string + parser::yysyntax_error_ (const context& yyctx) const + { + // Its maximum. + enum { YYARGS_MAX = 5 }; + // Arguments of yyformat. + symbol_kind_type yyarg[YYARGS_MAX]; + int yycount = yy_syntax_error_arguments_ (yyctx, yyarg, YYARGS_MAX); + + char const* yyformat = YY_NULLPTR; + switch (yycount) + { +#define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + default: // Avoid compiler warnings. + YYCASE_ (0, YY_("syntax error")); + YYCASE_ (1, YY_("syntax error, unexpected %s")); + YYCASE_ (2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_ (3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_ (4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_ (5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +#undef YYCASE_ + } + + std::string yyres; + // Argument number. + std::ptrdiff_t yyi = 0; + for (char const* yyp = yyformat; *yyp; ++yyp) + if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount) + { + yyres += symbol_name (yyarg[yyi++]); + ++yyp; + } + else + yyres += *yyp; + return yyres; + } + + + const short parser::yypact_ninf_ = -242; + + const short parser::yytable_ninf_ = -177; + + const short + parser::yypact_[] = + { + 9, -62, -14, -242, 54, 9, -242, -242, -242, -242, + -242, -20, -242, 11, -22, -242, -242, -242, -7, 732, + -242, -242, 27, -13, -242, -242, 22, 22, -242, 42, + -242, -242, -242, -242, -242, -242, -242, 732, 598, -7, + 732, 732, -36, 3, -242, -242, -242, -242, -242, -242, + -242, 845, -242, -242, -242, -242, 16, -242, -242, -242, + -242, -242, -242, 20, 65, -242, 125, -242, -242, -242, + -242, -242, 139, 357, 386, 429, -242, -242, -4, 52, + -242, -242, -242, -242, -242, -242, 69, 62, -7, 77, + -242, -242, 83, 82, -242, -242, 87, 1060, 598, -242, + 1708, 74, 90, -242, -242, -242, -242, -242, -242, -242, + -242, 732, 732, 732, 732, 732, 732, 732, 732, 732, + 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, + 22, 22, 799, -16, -242, -242, 732, -7, -242, 939, + -242, -242, 732, -7, 732, -242, 732, 1470, 732, -242, + 1625, 80, 80, 1739, 790, 533, 533, 111, 111, 111, + 111, 1749, 1780, 594, -45, -45, -242, -242, -242, -242, + -242, -242, -242, 1510, -242, -242, 34, -242, 92, 732, + 91, -18, 97, 103, 104, 105, 108, 193, 100, 102, + 121, 665, -242, 269, 269, -242, -242, 979, -242, -242, + -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, + -242, -242, -242, -242, -242, -242, -242, -242, 123, 124, + 129, -242, -242, 866, -242, -242, -242, -242, 83, 1470, + 92, 1550, 1589, 110, 1708, 732, -242, -242, 732, 1660, + -242, 117, -242, 732, 732, 494, -7, 732, 84, 131, + 132, -242, -242, -242, -242, 1695, -242, 40, 40, -242, + -242, -242, -242, -242, 142, 147, 148, 149, -7, -242, + -242, 732, 732, 732, 732, 732, 732, 732, 732, 732, + 732, 732, 158, 732, 164, 1708, 37, -242, 156, 1226, + 1260, 162, -242, 1022, 10, 1294, -242, -242, -242, 732, + 732, 732, 732, 1708, 1708, 1708, 1708, 1708, 1708, 1708, + 1708, 1708, 1708, 1708, 168, 1328, 732, -242, -242, 1019, + 1019, 732, 732, -7, 62, 1362, 1104, 1148, 1192, 732, + -242, 44, 199, -242, 167, 1708, 1396, 198, -242, 170, + 173, 732, 180, 732, 184, 732, 51, -242, 1019, 494, + 1019, 732, -242, -242, 57, -242, 72, -242, 81, -242, + -242, 194, -242, 1430, 186, 188, 189, 1019, 1019, -242, + -242, -242, -242, -242 + }; + + const unsigned char + parser::yydefact_[] = + { + 3, 0, 0, 193, 0, 2, 6, 7, 9, 10, + 11, 0, 194, 0, 0, 1, 4, 5, 17, 0, + 8, 196, 0, 0, 16, 192, 0, 0, 184, 0, + 200, 199, 186, 187, 188, 189, 190, 0, 162, 0, + 0, 0, 0, 0, 195, 197, 178, 180, 181, 182, + 183, 0, 75, 76, 77, 78, 116, 117, 118, 142, + 143, 119, 120, 121, 122, 123, 0, 138, 139, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 0, + 134, 135, 136, 137, 140, 141, 0, 0, 0, 0, + 146, 147, 0, 0, 150, 151, 0, 0, 162, 185, + 161, 0, 158, 159, 163, 115, 114, 177, 179, 191, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 145, 162, 0, 12, 0, + 14, 15, 0, 0, 0, 113, 0, 161, 0, 165, + 0, 106, 107, 94, 95, 96, 97, 98, 99, 100, + 101, 103, 104, 105, 108, 109, 110, 111, 112, 148, + 149, 152, 153, 0, 168, 167, 0, 158, 164, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 40, 0, 0, 42, 18, 0, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 0, 169, + 0, 170, 171, 0, 172, 173, 174, 175, 176, 0, + 0, 0, 0, 0, 160, 0, 166, 154, 162, 0, + 54, 0, 55, 0, 0, 72, 0, 0, 0, 0, + 0, 66, 67, 68, 70, 0, 169, 79, 80, 39, + 41, 45, 43, 44, 0, 0, 0, 0, 0, 81, + 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 102, 0, 49, 0, 0, + 0, 0, 71, 0, 0, 0, 64, 65, 69, 0, + 0, 0, 0, 83, 89, 90, 91, 92, 93, 84, + 85, 86, 88, 87, 0, 0, 162, 155, 56, 0, + 0, 74, 0, 0, 0, 0, 0, 0, 0, 162, + 198, 0, 57, 59, 0, 73, 0, 0, 63, 0, + 0, 162, 0, 162, 0, 162, 0, 156, 0, 72, + 0, 0, 46, 48, 0, 51, 0, 53, 0, 157, + 58, 0, 61, 0, 0, 0, 0, 0, 0, 47, + 50, 52, 60, 62 + }; + + const short + parser::yypgoto_[] = + { + -242, -242, -242, 232, 237, -242, -242, -242, -242, -194, + -76, -242, -242, -242, -242, -242, -242, -242, -242, -242, + -242, -242, -242, -242, -242, -242, -242, -242, -242, -242, + -242, -242, -98, -242, 215, -241, -242, -242, -242, -242, + -138, -101, -242, -19, -17, -51, -24, -242, -242, -242, + -124, 76, -242, 115, -242, 66, -242, -242, -242, 183, + 206, 239, 252, -242, -242, 0, 5, -242, -12, -242, + -242, -242, -242 + }; + + const short + parser::yydefgoto_[] = + { + 0, 4, 5, 6, 7, 8, 9, 10, 23, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 291, 334, 100, 218, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 101, 177, 103, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85 + }; + + const short + parser::yytable_[] = + { + 11, 219, 22, 260, 292, 11, 13, 90, 94, 91, + 95, 140, 1, 2, 102, 221, 174, 18, 24, 241, + 12, -176, -176, 14, -176, 87, 92, 92, 322, 242, + 88, 93, 93, 136, 127, 128, 129, -176, 220, 104, + -176, -169, -169, 19, -169, -170, -170, 134, -170, 135, + 29, 107, 108, 323, 15, 256, 256, -169, 20, 219, + -169, -170, 21, 89, -170, 86, 92, 3, 29, 221, + 221, 93, 237, 221, 102, 317, 3, 148, -176, -176, + 148, 132, 347, 96, 268, 176, 109, 148, 141, 359, + -171, -171, 3, -171, 148, 364, 220, 137, -169, -169, + 148, 139, -170, -170, 12, 3, -171, 256, 292, -171, + 365, 169, 171, 170, 172, 148, 138, 148, 142, 366, + 136, 221, 12, 3, 148, 332, 333, 143, 144, 238, + 92, 92, 149, 175, 243, 93, 93, 178, 240, 228, + 244, 245, 246, 230, 93, 247, 251, -171, -171, 252, + 130, 131, 284, 29, 360, 288, 362, 125, 126, 127, + 128, 129, 112, 113, -172, -172, 132, -172, 253, 133, + 261, 262, 108, 372, 373, 250, 263, 296, 297, 299, + -172, 219, 219, -172, 300, 301, 302, 286, 125, 126, + 127, 128, 129, 228, 228, 221, 221, 228, 93, 93, + 314, 316, 93, 318, 134, 329, 135, 12, 3, 321, + 219, 256, 219, 348, 349, 222, 351, 352, 220, 220, + 353, -172, -172, 92, 221, 221, 221, 355, 93, 219, + 219, 357, 367, 369, 51, 370, 371, 16, 134, 134, + 135, 135, 17, 221, 221, 228, 294, 220, 338, 220, + 93, 361, 97, 249, 223, 105, 106, 92, 92, 0, + 0, 0, 93, 93, 0, 331, 220, 220, 175, 222, + 222, 248, 0, 222, 134, 0, 135, 21, 346, 0, + 0, 47, 48, 49, 50, 0, 0, 0, 0, 0, + 354, 0, 356, 92, 358, 0, 0, 29, 93, 0, + 0, 0, 33, 34, 35, 36, 0, 0, 257, 258, + 89, 0, 223, 147, 0, 0, 0, 0, 0, 228, + 228, 222, 224, 337, 93, 93, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 225, 0, 173, 228, 228, + 228, 12, 3, 93, 93, 93, 0, 229, 0, 231, + 293, 232, 0, 234, 0, 0, 0, 228, 228, 0, + 0, 0, 93, 93, 0, 0, 224, 224, 226, 0, + 224, 0, -173, -173, 0, -173, 0, 0, 0, 0, + 0, 227, 0, 0, 239, 222, 222, 0, -173, 225, + 225, -173, 0, 225, 0, 0, 255, 0, 0, 0, + 0, -174, -174, 0, -174, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 222, 222, 222, -174, 224, 0, + -174, 0, 226, 226, 223, 223, 226, 0, 0, -173, + -173, 0, 0, 222, 222, 227, 227, 0, 0, 227, + 285, 225, 0, 0, -175, -175, 0, -175, 289, 290, + 0, 0, 295, 223, 293, 223, 0, 0, -174, -174, + -175, 0, 0, -175, 0, 0, 0, 0, 0, 0, + 0, 0, 223, 223, 226, 0, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 227, 315, 0, + 0, 0, 224, 224, 0, 0, 0, 0, 0, 0, + 0, -175, -175, 0, 325, 326, 327, 328, 0, 0, + 0, 0, 29, 0, 0, 225, 225, 33, 34, 35, + 36, 224, 224, 224, 0, 89, 335, 336, 0, 0, + 0, 0, 0, 193, 194, 0, 0, 0, 0, 0, + 224, 224, 0, 0, 225, 225, 225, 0, 226, 226, + 0, 0, 0, 0, 0, 0, 363, 0, 0, 0, + 0, 227, 227, 225, 225, 0, 12, 3, 0, 0, + 0, 0, 0, 0, 112, 113, 0, 226, 226, 226, + 118, 119, 120, 121, 0, 0, 0, 0, 0, 0, + 227, 227, 227, 25, 0, 0, 226, 226, 0, 0, + 125, 126, 127, 128, 129, 0, 0, 0, 0, 227, + 227, 0, 0, 26, 27, 28, 29, 30, 31, 32, + 0, 33, 34, 35, 36, 37, 0, 0, 0, 98, + 99, 0, 0, 39, 0, 112, 113, 0, 0, 116, + 117, 118, 119, 120, 121, 0, 0, 0, 0, 40, + 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 25, 125, 126, 127, 128, 129, 42, 0, 0, 43, + 12, 3, 21, 44, 45, 46, 47, 48, 49, 50, + 26, 27, 28, 29, 30, 31, 32, 0, 33, 34, + 35, 36, 37, 0, 0, 0, 38, 0, 0, 0, + 39, 0, 254, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 40, 41, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, + 0, 0, 0, 42, 0, 0, 43, 12, 3, 21, + 44, 45, 46, 47, 48, 49, 50, 26, 27, 28, + 29, 30, 31, 32, 0, 33, 34, 35, 36, 37, + 0, 0, 0, 38, 0, 0, 0, 39, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 40, 41, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, + 42, 0, 0, 43, 12, 3, 21, 44, 45, 46, + 47, 48, 49, 50, 26, 27, 28, 29, 30, 31, + 32, 0, 33, 34, 35, 36, 37, 0, 0, 0, + 98, 112, 113, 0, 39, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 0, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 264, 265, 0, 266, 267, 42, 0, 0, + 43, 12, 3, 21, 44, 45, 46, 47, 48, 49, + 50, 130, 110, 111, 29, 0, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 0, 132, 0, 0, + 268, 0, 0, 0, 0, 269, 270, 0, 0, 122, + 123, 124, 125, 126, 127, 128, 129, 0, 0, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 0, 0, 0, 0, 0, 0, 0, 179, 12, 3, + 180, 181, 182, 0, 183, 184, 185, 0, 186, 187, + 188, 189, 190, 191, 26, 0, 0, 29, 0, 0, + 0, 0, 33, 34, 35, 36, 0, 0, 139, 192, + 89, 0, 0, 0, 0, 0, 0, 179, 193, 194, + 180, 181, 182, 0, 183, 184, 185, 0, 186, 187, + 188, 189, 190, 191, 26, 0, 0, 29, 0, 0, + 0, 0, 33, 34, 35, 36, 0, 0, 139, 259, + 89, 12, 3, 0, 0, 0, 0, 179, 193, 194, + 180, 181, 182, 0, 183, 184, 185, 0, 186, 187, + 188, 189, 190, 191, 26, 0, 0, 29, 0, 0, + 29, 0, 33, 34, 35, 36, 0, 0, 139, 0, + 89, 12, 3, 132, 0, 0, 268, 0, 193, 194, + 0, 269, 270, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 0, 0, 145, 0, + 0, 12, 3, 146, 12, 3, 0, 0, 111, 0, + 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 340, 0, 0, 0, 0, 341, 0, 0, + 0, 0, 111, 0, 0, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 122, 123, + 124, 125, 126, 127, 128, 129, 342, 0, 0, 0, + 0, 343, 0, 0, 0, 0, 111, 0, 0, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 122, 123, 124, 125, 126, 127, 128, 129, + 344, 0, 0, 0, 0, 345, 0, 0, 0, 0, + 111, 0, 0, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 319, 0, 122, 123, 124, 125, + 126, 127, 128, 129, 111, 0, 0, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 320, 0, + 122, 123, 124, 125, 126, 127, 128, 129, 111, 0, + 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 324, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 111, 0, 0, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 330, 0, 122, 123, + 124, 125, 126, 127, 128, 129, 111, 0, 0, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 339, 0, 122, 123, 124, 125, 126, 127, 128, 129, + 111, 0, 0, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 350, 0, 122, 123, 124, 125, + 126, 127, 128, 129, 111, 0, 0, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 368, 0, + 122, 123, 124, 125, 126, 127, 128, 129, 111, 0, + 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 233, 0, 0, 0, 0, 0, 111, 0, + 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 236, 0, 0, 0, 0, 0, 111, 0, + 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 282, 0, 0, 0, 0, 0, 111, 0, + 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 283, 0, 0, 0, 0, 111, 0, 0, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 122, 123, 124, 125, 126, 127, 128, + 129, 235, 0, 111, 0, 0, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, + 123, 124, 125, 126, 127, 128, 129, 287, 111, 0, + 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, + 128, 129, 298, 111, 0, 0, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 111, 0, 0, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 0, 0, 0, + 0, 0, 122, 123, 124, 125, 126, 127, 128, 129, + 112, 113, 0, 115, 116, 117, 118, 119, 120, 121, + 112, 113, 0, 0, 116, 117, 118, 119, 120, 121, + 0, 0, 0, 122, 123, 124, 125, 126, 127, 128, + 129, 0, 0, 0, 123, 124, 125, 126, 127, 128, + 129, 112, 113, 0, 0, 116, 117, 118, 119, 120, + 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 124, 125, 126, 127, + 128, 129 + }; + + const short + parser::yycheck_[] = + { + 0, 139, 14, 197, 245, 5, 1, 26, 27, 26, + 27, 87, 3, 4, 38, 139, 32, 37, 18, 37, + 82, 25, 26, 37, 28, 38, 26, 27, 18, 47, + 43, 26, 27, 37, 79, 80, 81, 41, 139, 39, + 44, 25, 26, 63, 28, 25, 26, 66, 28, 66, + 28, 87, 88, 43, 0, 193, 194, 41, 47, 197, + 44, 41, 84, 41, 44, 38, 66, 83, 28, 193, + 194, 66, 38, 197, 98, 38, 83, 43, 82, 83, + 43, 41, 38, 41, 44, 136, 83, 43, 88, 38, + 25, 26, 83, 28, 43, 38, 197, 45, 82, 83, + 43, 39, 82, 83, 82, 83, 41, 245, 349, 44, + 38, 130, 131, 130, 131, 43, 47, 43, 41, 38, + 37, 245, 82, 83, 43, 319, 320, 45, 41, 37, + 130, 131, 42, 133, 37, 130, 131, 137, 47, 139, + 37, 37, 37, 143, 139, 37, 46, 82, 83, 47, + 25, 26, 42, 28, 348, 38, 350, 77, 78, 79, + 80, 81, 51, 52, 25, 26, 41, 28, 47, 44, + 47, 47, 88, 367, 368, 187, 47, 46, 46, 37, + 41, 319, 320, 44, 37, 37, 37, 238, 77, 78, + 79, 80, 81, 193, 194, 319, 320, 197, 193, 194, + 42, 37, 197, 47, 223, 37, 223, 82, 83, 47, + 348, 349, 350, 14, 47, 139, 18, 47, 319, 320, + 47, 82, 83, 223, 348, 349, 350, 47, 223, 367, + 368, 47, 38, 47, 19, 47, 47, 5, 257, 258, + 257, 258, 5, 367, 368, 245, 246, 348, 324, 350, + 245, 349, 37, 187, 139, 40, 41, 257, 258, -1, + -1, -1, 257, 258, -1, 316, 367, 368, 268, 193, + 194, 78, -1, 197, 293, -1, 293, 84, 329, -1, + -1, 88, 89, 90, 91, -1, -1, -1, -1, -1, + 341, -1, 343, 293, 345, -1, -1, 28, 293, -1, + -1, -1, 33, 34, 35, 36, -1, -1, 193, 194, + 41, -1, 197, 98, -1, -1, -1, -1, -1, 319, + 320, 245, 139, 323, 319, 320, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 139, -1, 132, 348, 349, + 350, 82, 83, 348, 349, 350, -1, 142, -1, 144, + 245, 146, -1, 148, -1, -1, -1, 367, 368, -1, + -1, -1, 367, 368, -1, -1, 193, 194, 139, -1, + 197, -1, 25, 26, -1, 28, -1, -1, -1, -1, + -1, 139, -1, -1, 179, 319, 320, -1, 41, 193, + 194, 44, -1, 197, -1, -1, 191, -1, -1, -1, + -1, 25, 26, -1, 28, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 348, 349, 350, 41, 245, -1, + 44, -1, 193, 194, 319, 320, 197, -1, -1, 82, + 83, -1, -1, 367, 368, 193, 194, -1, -1, 197, + 235, 245, -1, -1, 25, 26, -1, 28, 243, 244, + -1, -1, 247, 348, 349, 350, -1, -1, 82, 83, + 41, -1, -1, 44, -1, -1, -1, -1, -1, -1, + -1, -1, 367, 368, 245, -1, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 245, 283, -1, + -1, -1, 319, 320, -1, -1, -1, -1, -1, -1, + -1, 82, 83, -1, 299, 300, 301, 302, -1, -1, + -1, -1, 28, -1, -1, 319, 320, 33, 34, 35, + 36, 348, 349, 350, -1, 41, 321, 322, -1, -1, + -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, + 367, 368, -1, -1, 348, 349, 350, -1, 319, 320, + -1, -1, -1, -1, -1, -1, 351, -1, -1, -1, + -1, 319, 320, 367, 368, -1, 82, 83, -1, -1, + -1, -1, -1, -1, 51, 52, -1, 348, 349, 350, + 57, 58, 59, 60, -1, -1, -1, -1, -1, -1, + 348, 349, 350, 5, -1, -1, 367, 368, -1, -1, + 77, 78, 79, 80, 81, -1, -1, -1, -1, 367, + 368, -1, -1, 25, 26, 27, 28, 29, 30, 31, + -1, 33, 34, 35, 36, 37, -1, -1, -1, 41, + 42, -1, -1, 45, -1, 51, 52, -1, -1, 55, + 56, 57, 58, 59, 60, -1, -1, -1, -1, 61, + 62, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 5, 77, 78, 79, 80, 81, 78, -1, -1, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 25, 26, 27, 28, 29, 30, 31, -1, 33, 34, + 35, 36, 37, -1, -1, -1, 41, -1, -1, -1, + 45, -1, 47, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 61, 62, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, + -1, -1, -1, 78, -1, -1, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 25, 26, 27, + 28, 29, 30, 31, -1, 33, 34, 35, 36, 37, + -1, -1, -1, 41, -1, -1, -1, 45, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 61, 62, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, + 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 25, 26, 27, 28, 29, 30, + 31, -1, 33, 34, 35, 36, 37, -1, -1, -1, + 41, 51, 52, -1, 45, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 61, 62, -1, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 6, 7, -1, 9, 10, 78, -1, -1, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 25, 47, 48, 28, -1, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, -1, 41, -1, -1, + 44, -1, -1, -1, -1, 49, 50, -1, -1, 74, + 75, 76, 77, 78, 79, 80, 81, -1, -1, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + -1, -1, -1, -1, -1, -1, -1, 8, 82, 83, + 11, 12, 13, -1, 15, 16, 17, -1, 19, 20, + 21, 22, 23, 24, 25, -1, -1, 28, -1, -1, + -1, -1, 33, 34, 35, 36, -1, -1, 39, 40, + 41, -1, -1, -1, -1, -1, -1, 8, 49, 50, + 11, 12, 13, -1, 15, 16, 17, -1, 19, 20, + 21, 22, 23, 24, 25, -1, -1, 28, -1, -1, + -1, -1, 33, 34, 35, 36, -1, -1, 39, 40, + 41, 82, 83, -1, -1, -1, -1, 8, 49, 50, + 11, 12, 13, -1, 15, 16, 17, -1, 19, 20, + 21, 22, 23, 24, 25, -1, -1, 28, -1, -1, + 28, -1, 33, 34, 35, 36, -1, -1, 39, -1, + 41, 82, 83, 41, -1, -1, 44, -1, 49, 50, + -1, 49, 50, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, -1, -1, 38, -1, + -1, 82, 83, 43, 82, 83, -1, -1, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 38, -1, -1, -1, -1, 43, -1, -1, + -1, -1, 48, -1, -1, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 74, 75, + 76, 77, 78, 79, 80, 81, 38, -1, -1, -1, + -1, 43, -1, -1, -1, -1, 48, -1, -1, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 74, 75, 76, 77, 78, 79, 80, 81, + 38, -1, -1, -1, -1, 43, -1, -1, -1, -1, + 48, -1, -1, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 38, -1, 74, 75, 76, 77, + 78, 79, 80, 81, 48, -1, -1, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, + 74, 75, 76, 77, 78, 79, 80, 81, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 38, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 48, -1, -1, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 38, -1, 74, 75, + 76, 77, 78, 79, 80, 81, 48, -1, -1, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 38, -1, 74, 75, 76, 77, 78, 79, 80, 81, + 48, -1, -1, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 38, -1, 74, 75, 76, 77, + 78, 79, 80, 81, 48, -1, -1, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, + 74, 75, 76, 77, 78, 79, 80, 81, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 42, -1, -1, -1, -1, -1, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 42, -1, -1, -1, -1, -1, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 42, -1, -1, -1, -1, -1, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 43, -1, -1, -1, -1, 48, -1, -1, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 74, 75, 76, 77, 78, 79, 80, + 81, 46, -1, 48, -1, -1, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, + 75, 76, 77, 78, 79, 80, 81, 47, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, + 80, 81, 47, 48, -1, -1, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 48, -1, -1, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 74, + 75, 76, 77, 78, 79, 80, 81, -1, -1, -1, + -1, -1, 74, 75, 76, 77, 78, 79, 80, 81, + 51, 52, -1, 54, 55, 56, 57, 58, 59, 60, + 51, 52, -1, -1, 55, 56, 57, 58, 59, 60, + -1, -1, -1, 74, 75, 76, 77, 78, 79, 80, + 81, -1, -1, -1, 75, 76, 77, 78, 79, 80, + 81, 51, 52, -1, -1, 55, 56, 57, 58, 59, + 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 76, 77, 78, 79, + 80, 81 + }; + + const unsigned char + parser::yystos_[] = + { + 0, 3, 4, 83, 102, 103, 104, 105, 106, 107, + 108, 166, 82, 167, 37, 0, 104, 105, 37, 63, + 47, 84, 169, 109, 166, 5, 25, 26, 27, 28, + 29, 30, 31, 33, 34, 35, 36, 37, 41, 45, + 61, 62, 78, 81, 85, 86, 87, 88, 89, 90, + 91, 135, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 38, 38, 43, 41, + 144, 145, 166, 167, 144, 145, 41, 135, 41, 42, + 135, 146, 147, 148, 166, 135, 135, 87, 88, 83, + 47, 48, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 74, 75, 76, 77, 78, 79, 80, 81, + 25, 26, 41, 44, 144, 145, 37, 45, 47, 39, + 111, 166, 41, 45, 41, 38, 43, 135, 43, 42, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 144, + 145, 144, 145, 135, 32, 166, 146, 147, 166, 8, + 11, 12, 13, 15, 16, 17, 19, 20, 21, 22, + 23, 24, 40, 49, 50, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 136, 141, + 142, 151, 152, 154, 160, 161, 162, 163, 166, 135, + 166, 135, 135, 42, 135, 46, 42, 38, 37, 135, + 47, 37, 47, 37, 37, 37, 37, 37, 78, 156, + 169, 46, 47, 47, 47, 135, 141, 154, 154, 40, + 110, 47, 47, 47, 6, 7, 9, 10, 44, 49, + 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 42, 43, 42, 135, 146, 47, 38, 135, + 135, 133, 136, 154, 166, 135, 46, 46, 47, 37, + 37, 37, 37, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 42, 135, 37, 38, 47, 38, + 38, 47, 18, 43, 38, 135, 135, 135, 135, 37, + 38, 146, 110, 110, 134, 135, 135, 166, 111, 38, + 38, 43, 38, 43, 38, 43, 146, 38, 14, 47, + 38, 18, 47, 47, 146, 47, 146, 47, 146, 38, + 110, 133, 110, 135, 38, 38, 38, 38, 38, 47, + 47, 47, 110, 110 + }; + + const unsigned char + parser::yyr1_[] = + { + 0, 101, 102, 102, 103, 103, 103, 103, 104, 105, + 105, 105, 106, 107, 108, 109, 109, 109, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, + 111, 112, 112, 113, 113, 114, 115, 116, 116, 117, + 118, 118, 119, 119, 120, 121, 121, 122, 123, 124, + 125, 126, 126, 127, 128, 128, 129, 130, 131, 132, + 132, 133, 133, 134, 134, 135, 135, 135, 135, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 137, 137, 137, 137, 137, 137, + 137, 137, 138, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 141, 141, 141, 141, 142, 142, 142, 142, + 143, 143, 143, 143, 144, 144, 145, 145, 146, 146, + 147, 147, 148, 149, 149, 150, 151, 152, 153, 154, + 154, 154, 154, 154, 154, 154, 154, 155, 155, 156, + 156, 156, 156, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 173 + }; + + const signed char + parser::yyr2_[] = + { + 0, 2, 1, 0, 2, 2, 1, 1, 3, 1, + 1, 1, 5, 4, 5, 3, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 2, 2, 1, 2, 2, 2, 6, 8, 6, 3, + 8, 6, 8, 6, 2, 2, 4, 5, 7, 5, + 9, 7, 9, 5, 3, 3, 2, 2, 2, 3, + 2, 1, 0, 1, 0, 1, 1, 1, 1, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, + 2, 2, 3, 3, 4, 6, 8, 9, 1, 1, + 3, 1, 0, 2, 3, 3, 4, 3, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 7, 1, + 1 + }; + + + + +#if S4DEBUG + const short + parser::yyrline_[] = + { + 0, 240, 240, 241, 245, 247, 249, 251, 256, 261, + 262, 263, 267, 272, 277, 282, 284, 287, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 315, + 316, 320, 322, 327, 329, 334, 339, 344, 346, 351, + 356, 358, 363, 365, 370, 375, 377, 382, 387, 392, + 397, 402, 404, 409, 414, 416, 421, 426, 431, 436, + 438, 443, 444, 448, 449, 453, 454, 455, 456, 460, + 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 478, 479, 480, 481, 482, 483, + 484, 485, 489, 493, 494, 495, 496, 497, 498, 499, + 500, 501, 502, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, + 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, + 533, 534, 538, 539, 540, 541, 545, 546, 547, 548, + 552, 553, 554, 555, 559, 561, 566, 568, 573, 574, + 578, 580, 586, 590, 592, 597, 602, 607, 612, 617, + 618, 619, 620, 621, 622, 623, 624, 628, 629, 633, + 634, 635, 636, 637, 640, 641, 642, 643, 644, 645, + 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, + 656 + }; + + void + parser::yy_stack_print_ () const + { + *yycdebug_ << "Stack now"; + for (stack_type::const_iterator + i = yystack_.begin (), + i_end = yystack_.end (); + i != i_end; ++i) + *yycdebug_ << ' ' << int (i->state); + *yycdebug_ << '\n'; + } + + void + parser::yy_reduce_print_ (int yyrule) const + { + int yylno = yyrline_[yyrule]; + int yynrhs = yyr2_[yyrule]; + // Print the symbols being reduced, and their result. + *yycdebug_ << "Reducing stack by rule " << yyrule - 1 + << " (line " << yylno << "):\n"; + // The symbols being reduced. + for (int yyi = 0; yyi < yynrhs; yyi++) + YY_SYMBOL_PRINT (" $" << yyi + 1 << " =", + yystack_[(yynrhs) - (yyi + 1)]); + } +#endif // S4DEBUG + + +#line 13 "parser.ypp" +} } } // xsk::gsc::s4 +#line 4109 "parser.cpp" + +#line 658 "parser.ypp" + + +void xsk::gsc::s4::parser::error(const xsk::gsc::location& loc, const std::string& msg) +{ + throw xsk::gsc::comp_error(loc, msg); +} diff --git a/src/s4/xsk/parser.hpp b/src/s4/xsk/parser.hpp new file mode 100644 index 00000000..dbbcdb21 --- /dev/null +++ b/src/s4/xsk/parser.hpp @@ -0,0 +1,4918 @@ +// A Bison parser, made by GNU Bison 3.7.5. + +// Skeleton interface for Bison LALR(1) parsers in C++ + +// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// As a special exception, you may create a larger work that contains +// part or all of the Bison parser skeleton and distribute that work +// under terms of your choice, so long as that work isn't itself a +// parser generator using the skeleton or a modified version thereof +// as a parser skeleton. Alternatively, if you modify or redistribute +// the parser skeleton itself, you may (at your option) remove this +// special exception, which will cause the skeleton and the resulting +// Bison output files to be licensed under the GNU General Public +// License without this special exception. + +// This special exception was added by the Free Software Foundation in +// version 2.2 of Bison. + + +/** + ** \file parser.hpp + ** Define the xsk::gsc::s4::parser class. + */ + +// C++ LALR(1) parser skeleton written by Akim Demaille. + +// DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, +// especially those whose name start with YY_ or yy_. They are +// private implementation details that can be changed or removed. + +#ifndef YY_S4_PARSER_HPP_INCLUDED +# define YY_S4_PARSER_HPP_INCLUDED +// "%code requires" blocks. +#line 33 "parser.ypp" + +#include "s4.hpp" +typedef void *yyscan_t; +#define YY_DECL xsk::gsc::s4::parser::symbol_type S4lex(yyscan_t yyscanner, xsk::gsc::location& loc) + +#line 55 "parser.hpp" + +# include +# include // std::abort +# include +# include +# include +# include + +#if defined __cplusplus +# define YY_CPLUSPLUS __cplusplus +#else +# define YY_CPLUSPLUS 199711L +#endif + +// Support move semantics when possible. +#if 201103L <= YY_CPLUSPLUS +# define YY_MOVE std::move +# define YY_MOVE_OR_COPY move +# define YY_MOVE_REF(Type) Type&& +# define YY_RVREF(Type) Type&& +# define YY_COPY(Type) Type +#else +# define YY_MOVE +# define YY_MOVE_OR_COPY copy +# define YY_MOVE_REF(Type) Type& +# define YY_RVREF(Type) const Type& +# define YY_COPY(Type) const Type& +#endif + +// Support noexcept when possible. +#if 201103L <= YY_CPLUSPLUS +# define YY_NOEXCEPT noexcept +# define YY_NOTHROW +#else +# define YY_NOEXCEPT +# define YY_NOTHROW throw () +#endif + +// Support constexpr when possible. +#if 201703 <= YY_CPLUSPLUS +# define YY_CONSTEXPR constexpr +#else +# define YY_CONSTEXPR +#endif + +#include +#ifndef S4_ASSERT +# include +# define S4_ASSERT assert +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YY_USE(E) ((void) (E)) +#else +# define YY_USE(E) /* empty */ +#endif + +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + +/* Debug traces. */ +#ifndef S4DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define S4DEBUG 1 +# else +# define S4DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define S4DEBUG 1 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined S4DEBUG */ + +#line 13 "parser.ypp" +namespace xsk { namespace gsc { namespace s4 { +#line 198 "parser.hpp" + + + + + /// A Bison parser. + class parser + { + public: +#ifndef S4STYPE + /// A buffer to store and retrieve objects. + /// + /// Sort of a variant, but does not keep track of the nature + /// of the stored data, since that knowledge is available + /// via the current parser state. + class semantic_type + { + public: + /// Type of *this. + typedef semantic_type self_type; + + /// Empty construction. + semantic_type () YY_NOEXCEPT + : yybuffer_ () + , yytypeid_ (YY_NULLPTR) + {} + + /// Construct and fill. + template + semantic_type (YY_RVREF (T) t) + : yytypeid_ (&typeid (T)) + { + S4_ASSERT (sizeof (T) <= size); + new (yyas_ ()) T (YY_MOVE (t)); + } + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + semantic_type (const self_type&) = delete; + /// Non copyable. + self_type& operator= (const self_type&) = delete; +#endif + + /// Destruction, allowed only if empty. + ~semantic_type () YY_NOEXCEPT + { + S4_ASSERT (!yytypeid_); + } + +# if 201103L <= YY_CPLUSPLUS + /// Instantiate a \a T in here from \a t. + template + T& + emplace (U&&... u) + { + S4_ASSERT (!yytypeid_); + S4_ASSERT (sizeof (T) <= size); + yytypeid_ = & typeid (T); + return *new (yyas_ ()) T (std::forward (u)...); + } +# else + /// Instantiate an empty \a T in here. + template + T& + emplace () + { + S4_ASSERT (!yytypeid_); + S4_ASSERT (sizeof (T) <= size); + yytypeid_ = & typeid (T); + return *new (yyas_ ()) T (); + } + + /// Instantiate a \a T in here from \a t. + template + T& + emplace (const T& t) + { + S4_ASSERT (!yytypeid_); + S4_ASSERT (sizeof (T) <= size); + yytypeid_ = & typeid (T); + return *new (yyas_ ()) T (t); + } +# endif + + /// Instantiate an empty \a T in here. + /// Obsolete, use emplace. + template + T& + build () + { + return emplace (); + } + + /// Instantiate a \a T in here from \a t. + /// Obsolete, use emplace. + template + T& + build (const T& t) + { + return emplace (t); + } + + /// Accessor to a built \a T. + template + T& + as () YY_NOEXCEPT + { + S4_ASSERT (yytypeid_); + S4_ASSERT (*yytypeid_ == typeid (T)); + S4_ASSERT (sizeof (T) <= size); + return *yyas_ (); + } + + /// Const accessor to a built \a T (for %printer). + template + const T& + as () const YY_NOEXCEPT + { + S4_ASSERT (yytypeid_); + S4_ASSERT (*yytypeid_ == typeid (T)); + S4_ASSERT (sizeof (T) <= size); + return *yyas_ (); + } + + /// Swap the content with \a that, of same type. + /// + /// Both variants must be built beforehand, because swapping the actual + /// data requires reading it (with as()), and this is not possible on + /// unconstructed variants: it would require some dynamic testing, which + /// should not be the variant's responsibility. + /// Swapping between built and (possibly) non-built is done with + /// self_type::move (). + template + void + swap (self_type& that) YY_NOEXCEPT + { + S4_ASSERT (yytypeid_); + S4_ASSERT (*yytypeid_ == *that.yytypeid_); + std::swap (as (), that.as ()); + } + + /// Move the content of \a that to this. + /// + /// Destroys \a that. + template + void + move (self_type& that) + { +# if 201103L <= YY_CPLUSPLUS + emplace (std::move (that.as ())); +# else + emplace (); + swap (that); +# endif + that.destroy (); + } + +# if 201103L <= YY_CPLUSPLUS + /// Move the content of \a that to this. + template + void + move (self_type&& that) + { + emplace (std::move (that.as ())); + that.destroy (); + } +#endif + + /// Copy the content of \a that to this. + template + void + copy (const self_type& that) + { + emplace (that.as ()); + } + + /// Destroy the stored \a T. + template + void + destroy () + { + as ().~T (); + yytypeid_ = YY_NULLPTR; + } + + private: +#if YY_CPLUSPLUS < 201103L + /// Non copyable. + semantic_type (const self_type&); + /// Non copyable. + self_type& operator= (const self_type&); +#endif + + /// Accessor to raw memory as \a T. + template + T* + yyas_ () YY_NOEXCEPT + { + void *yyp = yybuffer_.yyraw; + return static_cast (yyp); + } + + /// Const accessor to raw memory as \a T. + template + const T* + yyas_ () const YY_NOEXCEPT + { + const void *yyp = yybuffer_.yyraw; + return static_cast (yyp); + } + + /// An auxiliary type to compute the largest semantic type. + union union_type + { + // anim + char dummy1[sizeof (anim_ptr)]; + + // animation + char dummy2[sizeof (animation_ptr)]; + + // animtree + char dummy3[sizeof (animtree_ptr)]; + + // color + char dummy4[sizeof (color_ptr)]; + + // constant + char dummy5[sizeof (constant_ptr)]; + + // define + char dummy6[sizeof (define_ptr)]; + + // empty_array + char dummy7[sizeof (empty_array_ptr)]; + + // expr_arguments + // expr_arguments_filled + // expr_arguments_empty + char dummy8[sizeof (expr_arguments_ptr)]; + + // expr_assign + char dummy9[sizeof (expr_assign_ptr)]; + + // expr_call + // expr_call_thread + // expr_call_childthread + char dummy10[sizeof (expr_call_ptr)]; + + // expr_call_function + // expr_call_pointer + char dummy11[sizeof (expr_call_type_ptr)]; + + // for_expr + // expr + // expr_compare + // expr_ternary + // expr_binary + // expr_primitive + char dummy12[sizeof (expr_ptr)]; + + // false + char dummy13[sizeof (false_ptr)]; + + // file + char dummy14[sizeof (file_ptr)]; + + // float + char dummy15[sizeof (float_ptr)]; + + // game + char dummy16[sizeof (game_ptr)]; + + // include + char dummy17[sizeof (include_ptr)]; + + // integer + char dummy18[sizeof (integer_ptr)]; + + // istring + char dummy19[sizeof (istring_ptr)]; + + // level + char dummy20[sizeof (level_ptr)]; + + // name + char dummy21[sizeof (name_ptr)]; + + // expr_function + // expr_add_array + // expr_array + // expr_field + // expr_size + // object + char dummy22[sizeof (node_ptr)]; + + // parameters + char dummy23[sizeof (parameters_ptr)]; + + // program + char dummy24[sizeof (program_ptr)]; + + // self + char dummy25[sizeof (self_ptr)]; + + // "file path" + // "identifier" + // "string literal" + // "localized string" + // "color" + // "float" + // "int" + // "octal int" + // "binary int" + // "hexadecimal int" + char dummy26[sizeof (std::string)]; + + // stmt_assign + char dummy27[sizeof (stmt_assign_ptr)]; + + // stmt_break + char dummy28[sizeof (stmt_break_ptr)]; + + // stmt_call + char dummy29[sizeof (stmt_call_ptr)]; + + // stmt_case + char dummy30[sizeof (stmt_case_ptr)]; + + // stmt_continue + char dummy31[sizeof (stmt_continue_ptr)]; + + // stmt_default + char dummy32[sizeof (stmt_default_ptr)]; + + // stmt_endon + char dummy33[sizeof (stmt_endon_ptr)]; + + // stmt_for + char dummy34[sizeof (stmt_for_ptr)]; + + // stmt_foreach + char dummy35[sizeof (stmt_foreach_ptr)]; + + // stmt_if + char dummy36[sizeof (stmt_if_ptr)]; + + // stmt_ifelse + char dummy37[sizeof (stmt_ifelse_ptr)]; + + // stmt_block + // stmt_list + char dummy38[sizeof (stmt_list_ptr)]; + + // stmt_notify + char dummy39[sizeof (stmt_notify_ptr)]; + + // stmt + // for_stmt + char dummy40[sizeof (stmt_ptr)]; + + // stmt_return + char dummy41[sizeof (stmt_return_ptr)]; + + // stmt_switch + char dummy42[sizeof (stmt_switch_ptr)]; + + // stmt_wait + char dummy43[sizeof (stmt_wait_ptr)]; + + // stmt_waitframe + char dummy44[sizeof (stmt_waitframe_ptr)]; + + // stmt_waittill + char dummy45[sizeof (stmt_waittill_ptr)]; + + // stmt_waittillframeend + char dummy46[sizeof (stmt_waittillframeend_ptr)]; + + // stmt_waittillmatch + char dummy47[sizeof (stmt_waittillmatch_ptr)]; + + // stmt_while + char dummy48[sizeof (stmt_while_ptr)]; + + // string + char dummy49[sizeof (string_ptr)]; + + // thisthread + char dummy50[sizeof (thisthread_ptr)]; + + // thread + char dummy51[sizeof (thread_ptr)]; + + // true + char dummy52[sizeof (true_ptr)]; + + // undefined + char dummy53[sizeof (undefined_ptr)]; + + // usingtree + char dummy54[sizeof (usingtree_ptr)]; + + // vector + char dummy55[sizeof (vector_ptr)]; + }; + + /// The size of the largest semantic type. + enum { size = sizeof (union_type) }; + + /// A buffer to store semantic values. + union + { + /// Strongest alignment constraints. + long double yyalign_me; + /// A buffer large enough to store any of the semantic values. + char yyraw[size]; + } yybuffer_; + + /// Whether the content is built: if defined, the name of the stored type. + const std::type_info *yytypeid_; + }; + +#else + typedef S4STYPE semantic_type; +#endif + /// Symbol locations. + typedef xsk::gsc::location location_type; + + /// Syntax errors thrown from user actions. + struct syntax_error : std::runtime_error + { + syntax_error (const location_type& l, const std::string& m) + : std::runtime_error (m) + , location (l) + {} + + syntax_error (const syntax_error& s) + : std::runtime_error (s.what ()) + , location (s.location) + {} + + ~syntax_error () YY_NOEXCEPT YY_NOTHROW; + + location_type location; + }; + + /// Token kinds. + struct token + { + enum token_kind_type + { + S4EMPTY = -2, + S4EOF = 0, // "end of file" + S4error = 1, // error + S4UNDEF = 2, // "invalid token" + INCLUDE = 3, // "#include" + USINGTREE = 4, // "#using_animtree" + ANIMTREE = 5, // "#animtree" + ENDON = 6, // "endon" + NOTIFY = 7, // "notify" + WAIT = 8, // "wait" + WAITTILL = 9, // "waittill" + WAITTILLMATCH = 10, // "waittillmatch" + WAITTILLFRAMEEND = 11, // "waittillframeend" + WAITFRAME = 12, // "waitframe" + IF = 13, // "if" + ELSE = 14, // "else" + WHILE = 15, // "while" + FOR = 16, // "for" + FOREACH = 17, // "foreach" + IN = 18, // "in" + SWITCH = 19, // "switch" + CASE = 20, // "case" + DEFAULT = 21, // "default" + BREAK = 22, // "break" + CONTINUE = 23, // "continue" + RETURN = 24, // "return" + THREAD = 25, // "thread" + CHILDTHREAD = 26, // "childthread" + THISTHREAD = 27, // "thisthread" + CALL = 28, // "call" + TRUE = 29, // "true" + FALSE = 30, // "false" + UNDEFINED = 31, // "undefined" + SIZE = 32, // "size" + GAME = 33, // "game" + SELF = 34, // "self" + ANIM = 35, // "anim" + LEVEL = 36, // "level" + LPAREN = 37, // "(" + RPAREN = 38, // ")" + LBRACE = 39, // "{" + RBRACE = 40, // "}" + LBRACKET = 41, // "[" + RBRACKET = 42, // "]" + COMMA = 43, // "," + DOT = 44, // "." + DOUBLECOLON = 45, // "::" + COLON = 46, // ":" + SEMICOLON = 47, // ";" + QMARK = 48, // "?" + INCREMENT = 49, // "++" + DECREMENT = 50, // "--" + LSHIFT = 51, // "<<" + RSHIFT = 52, // ">>" + OR = 53, // "||" + AND = 54, // "&&" + EQUALITY = 55, // "==" + INEQUALITY = 56, // "!=" + LESS_EQUAL = 57, // "<=" + GREATER_EQUAL = 58, // ">=" + LESS = 59, // "<" + GREATER = 60, // ">" + NOT = 61, // "!" + COMPLEMENT = 62, // "~" + ASSIGN = 63, // "=" + ASSIGN_ADD = 64, // "+=" + ASSIGN_SUB = 65, // "-=" + ASSIGN_MULT = 66, // "*=" + ASSIGN_DIV = 67, // "/=" + ASSIGN_MOD = 68, // "%=" + ASSIGN_BITWISE_OR = 69, // "|=" + ASSIGN_BITWISE_AND = 70, // "&=" + ASSIGN_BITWISE_EXOR = 71, // "^=" + ASSIGN_RSHIFT = 72, // ">>=" + ASSIGN_LSHIFT = 73, // "<<=" + BITWISE_OR = 74, // "|" + BITWISE_AND = 75, // "&" + BITWISE_EXOR = 76, // "^" + ADD = 77, // "+" + SUB = 78, // "-" + MULT = 79, // "*" + DIV = 80, // "/" + MOD = 81, // "%" + FILE = 82, // "file path" + NAME = 83, // "identifier" + STRING = 84, // "string literal" + ISTRING = 85, // "localized string" + COLOR = 86, // "color" + FLOAT = 87, // "float" + INT_DEC = 88, // "int" + INT_OCT = 89, // "octal int" + INT_BIN = 90, // "binary int" + INT_HEX = 91, // "hexadecimal int" + ADD_ARRAY = 92, // ADD_ARRAY + THEN = 93, // THEN + TERN = 94, // TERN + NEG = 95, // NEG + ANIMREF = 96, // ANIMREF + PREINC = 97, // PREINC + PREDEC = 98, // PREDEC + POSTINC = 99, // POSTINC + POSTDEC = 100 // POSTDEC + }; + /// Backward compatibility alias (Bison 3.6). + typedef token_kind_type yytokentype; + }; + + /// Token kind, as returned by yylex. + typedef token::yytokentype token_kind_type; + + /// Backward compatibility alias (Bison 3.6). + typedef token_kind_type token_type; + + /// Symbol kinds. + struct symbol_kind + { + enum symbol_kind_type + { + YYNTOKENS = 101, ///< Number of tokens. + S_YYEMPTY = -2, + S_YYEOF = 0, // "end of file" + S_YYerror = 1, // error + S_YYUNDEF = 2, // "invalid token" + S_INCLUDE = 3, // "#include" + S_USINGTREE = 4, // "#using_animtree" + S_ANIMTREE = 5, // "#animtree" + S_ENDON = 6, // "endon" + S_NOTIFY = 7, // "notify" + S_WAIT = 8, // "wait" + S_WAITTILL = 9, // "waittill" + S_WAITTILLMATCH = 10, // "waittillmatch" + S_WAITTILLFRAMEEND = 11, // "waittillframeend" + S_WAITFRAME = 12, // "waitframe" + S_IF = 13, // "if" + S_ELSE = 14, // "else" + S_WHILE = 15, // "while" + S_FOR = 16, // "for" + S_FOREACH = 17, // "foreach" + S_IN = 18, // "in" + S_SWITCH = 19, // "switch" + S_CASE = 20, // "case" + S_DEFAULT = 21, // "default" + S_BREAK = 22, // "break" + S_CONTINUE = 23, // "continue" + S_RETURN = 24, // "return" + S_THREAD = 25, // "thread" + S_CHILDTHREAD = 26, // "childthread" + S_THISTHREAD = 27, // "thisthread" + S_CALL = 28, // "call" + S_TRUE = 29, // "true" + S_FALSE = 30, // "false" + S_UNDEFINED = 31, // "undefined" + S_SIZE = 32, // "size" + S_GAME = 33, // "game" + S_SELF = 34, // "self" + S_ANIM = 35, // "anim" + S_LEVEL = 36, // "level" + S_LPAREN = 37, // "(" + S_RPAREN = 38, // ")" + S_LBRACE = 39, // "{" + S_RBRACE = 40, // "}" + S_LBRACKET = 41, // "[" + S_RBRACKET = 42, // "]" + S_COMMA = 43, // "," + S_DOT = 44, // "." + S_DOUBLECOLON = 45, // "::" + S_COLON = 46, // ":" + S_SEMICOLON = 47, // ";" + S_QMARK = 48, // "?" + S_INCREMENT = 49, // "++" + S_DECREMENT = 50, // "--" + S_LSHIFT = 51, // "<<" + S_RSHIFT = 52, // ">>" + S_OR = 53, // "||" + S_AND = 54, // "&&" + S_EQUALITY = 55, // "==" + S_INEQUALITY = 56, // "!=" + S_LESS_EQUAL = 57, // "<=" + S_GREATER_EQUAL = 58, // ">=" + S_LESS = 59, // "<" + S_GREATER = 60, // ">" + S_NOT = 61, // "!" + S_COMPLEMENT = 62, // "~" + S_ASSIGN = 63, // "=" + S_ASSIGN_ADD = 64, // "+=" + S_ASSIGN_SUB = 65, // "-=" + S_ASSIGN_MULT = 66, // "*=" + S_ASSIGN_DIV = 67, // "/=" + S_ASSIGN_MOD = 68, // "%=" + S_ASSIGN_BITWISE_OR = 69, // "|=" + S_ASSIGN_BITWISE_AND = 70, // "&=" + S_ASSIGN_BITWISE_EXOR = 71, // "^=" + S_ASSIGN_RSHIFT = 72, // ">>=" + S_ASSIGN_LSHIFT = 73, // "<<=" + S_BITWISE_OR = 74, // "|" + S_BITWISE_AND = 75, // "&" + S_BITWISE_EXOR = 76, // "^" + S_ADD = 77, // "+" + S_SUB = 78, // "-" + S_MULT = 79, // "*" + S_DIV = 80, // "/" + S_MOD = 81, // "%" + S_FILE = 82, // "file path" + S_NAME = 83, // "identifier" + S_STRING = 84, // "string literal" + S_ISTRING = 85, // "localized string" + S_COLOR = 86, // "color" + S_FLOAT = 87, // "float" + S_INT_DEC = 88, // "int" + S_INT_OCT = 89, // "octal int" + S_INT_BIN = 90, // "binary int" + S_INT_HEX = 91, // "hexadecimal int" + S_ADD_ARRAY = 92, // ADD_ARRAY + S_THEN = 93, // THEN + S_TERN = 94, // TERN + S_NEG = 95, // NEG + S_ANIMREF = 96, // ANIMREF + S_PREINC = 97, // PREINC + S_PREDEC = 98, // PREDEC + S_POSTINC = 99, // POSTINC + S_POSTDEC = 100, // POSTDEC + S_YYACCEPT = 101, // $accept + S_root = 102, // root + S_program = 103, // program + S_include = 104, // include + S_define = 105, // define + S_usingtree = 106, // usingtree + S_constant = 107, // constant + S_thread = 108, // thread + S_parameters = 109, // parameters + S_stmt = 110, // stmt + S_stmt_block = 111, // stmt_block + S_stmt_list = 112, // stmt_list + S_stmt_call = 113, // stmt_call + S_stmt_assign = 114, // stmt_assign + S_stmt_endon = 115, // stmt_endon + S_stmt_notify = 116, // stmt_notify + S_stmt_wait = 117, // stmt_wait + S_stmt_waittill = 118, // stmt_waittill + S_stmt_waittillmatch = 119, // stmt_waittillmatch + S_stmt_waittillframeend = 120, // stmt_waittillframeend + S_stmt_waitframe = 121, // stmt_waitframe + S_stmt_if = 122, // stmt_if + S_stmt_ifelse = 123, // stmt_ifelse + S_stmt_while = 124, // stmt_while + S_stmt_for = 125, // stmt_for + S_stmt_foreach = 126, // stmt_foreach + S_stmt_switch = 127, // stmt_switch + S_stmt_case = 128, // stmt_case + S_stmt_default = 129, // stmt_default + S_stmt_break = 130, // stmt_break + S_stmt_continue = 131, // stmt_continue + S_stmt_return = 132, // stmt_return + S_for_stmt = 133, // for_stmt + S_for_expr = 134, // for_expr + S_expr = 135, // expr + S_expr_assign = 136, // expr_assign + S_expr_compare = 137, // expr_compare + S_expr_ternary = 138, // expr_ternary + S_expr_binary = 139, // expr_binary + S_expr_primitive = 140, // expr_primitive + S_expr_call = 141, // expr_call + S_expr_call_thread = 142, // expr_call_thread + S_expr_call_childthread = 143, // expr_call_childthread + S_expr_call_function = 144, // expr_call_function + S_expr_call_pointer = 145, // expr_call_pointer + S_expr_arguments = 146, // expr_arguments + S_expr_arguments_filled = 147, // expr_arguments_filled + S_expr_arguments_empty = 148, // expr_arguments_empty + S_expr_function = 149, // expr_function + S_expr_add_array = 150, // expr_add_array + S_expr_array = 151, // expr_array + S_expr_field = 152, // expr_field + S_expr_size = 153, // expr_size + S_object = 154, // object + S_float = 155, // float + S_integer = 156, // integer + S_thisthread = 157, // thisthread + S_empty_array = 158, // empty_array + S_undefined = 159, // undefined + S_game = 160, // game + S_self = 161, // self + S_anim = 162, // anim + S_level = 163, // level + S_animation = 164, // animation + S_animtree = 165, // animtree + S_name = 166, // name + S_file = 167, // file + S_istring = 168, // istring + S_string = 169, // string + S_color = 170, // color + S_vector = 171, // vector + S_false = 172, // false + S_true = 173 // true + }; + }; + + /// (Internal) symbol kind. + typedef symbol_kind::symbol_kind_type symbol_kind_type; + + /// The number of tokens. + static const symbol_kind_type YYNTOKENS = symbol_kind::YYNTOKENS; + + /// A complete symbol. + /// + /// Expects its Base type to provide access to the symbol kind + /// via kind (). + /// + /// Provide access to semantic value and location. + template + struct basic_symbol : Base + { + /// Alias to Base. + typedef Base super_type; + + /// Default constructor. + basic_symbol () + : value () + , location () + {} + +#if 201103L <= YY_CPLUSPLUS + /// Move constructor. + basic_symbol (basic_symbol&& that) + : Base (std::move (that)) + , value () + , location (std::move (that.location)) + { + switch (this->kind ()) + { + case symbol_kind::S_anim: // anim + value.move< anim_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_animation: // animation + value.move< animation_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_animtree: // animtree + value.move< animtree_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_color: // color + value.move< color_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_constant: // constant + value.move< constant_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_define: // define + value.move< define_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_empty_array: // empty_array + value.move< empty_array_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.move< expr_arguments_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.move< expr_assign_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.move< expr_call_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.move< expr_call_type_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.move< expr_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_false: // false + value.move< false_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_file: // file + value.move< file_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_float: // float + value.move< float_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_game: // game + value.move< game_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_include: // include + value.move< include_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_integer: // integer + value.move< integer_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_istring: // istring + value.move< istring_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_level: // level + value.move< level_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_name: // name + value.move< name_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.move< node_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_parameters: // parameters + value.move< parameters_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_program: // program + value.move< program_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_self: // self + value.move< self_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.move< std::string > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< stmt_assign_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< stmt_break_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< stmt_call_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< stmt_case_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< stmt_continue_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< stmt_default_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< stmt_endon_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< stmt_for_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< stmt_foreach_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< stmt_if_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< stmt_ifelse_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.move< stmt_list_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< stmt_notify_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.move< stmt_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< stmt_return_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< stmt_switch_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< stmt_wait_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< stmt_waitframe_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< stmt_waittill_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< stmt_waittillframeend_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< stmt_waittillmatch_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< stmt_while_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_string: // string + value.move< string_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_thisthread: // thisthread + value.move< thisthread_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_thread: // thread + value.move< thread_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_true: // true + value.move< true_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_undefined: // undefined + value.move< undefined_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_usingtree: // usingtree + value.move< usingtree_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_vector: // vector + value.move< vector_ptr > (std::move (that.value)); + break; + + default: + break; + } + + } +#endif + + /// Copy constructor. + basic_symbol (const basic_symbol& that); + + /// Constructors for typed symbols. +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, location_type&& l) + : Base (t) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const location_type& l) + : Base (t) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, anim_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const anim_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, animation_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const animation_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, animtree_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const animtree_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, color_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const color_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, constant_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const constant_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, define_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const define_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, empty_array_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const empty_array_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, expr_arguments_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const expr_arguments_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, expr_assign_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const expr_assign_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, expr_call_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const expr_call_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, expr_call_type_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const expr_call_type_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, expr_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const expr_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, false_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const false_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, file_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const file_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, float_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const float_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, game_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const game_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, include_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const include_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, integer_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const integer_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, istring_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const istring_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, level_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const level_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, name_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const name_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, node_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const node_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, parameters_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const parameters_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, program_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const program_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, self_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const self_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, std::string&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const std::string& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_assign_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_assign_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_break_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_break_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_call_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_call_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_case_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_case_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_continue_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_continue_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_default_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_default_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_endon_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_endon_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_for_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_for_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_foreach_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_foreach_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_if_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_if_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_ifelse_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_ifelse_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_list_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_list_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_notify_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_notify_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_return_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_return_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_switch_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_switch_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_wait_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_wait_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_waitframe_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_waitframe_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_waittill_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_waittill_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_waittillframeend_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_waittillframeend_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_waittillmatch_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_waittillmatch_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, stmt_while_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const stmt_while_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, string_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const string_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, thisthread_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const thisthread_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, thread_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const thread_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, true_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const true_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, undefined_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const undefined_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, usingtree_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const usingtree_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, vector_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const vector_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + + /// Destroy the symbol. + ~basic_symbol () + { + clear (); + } + + /// Destroy contents, and record that is empty. + void clear () YY_NOEXCEPT + { + // User destructor. + symbol_kind_type yykind = this->kind (); + basic_symbol& yysym = *this; + (void) yysym; + switch (yykind) + { + default: + break; + } + + // Value type destructor. +switch (yykind) + { + case symbol_kind::S_anim: // anim + value.template destroy< anim_ptr > (); + break; + + case symbol_kind::S_animation: // animation + value.template destroy< animation_ptr > (); + break; + + case symbol_kind::S_animtree: // animtree + value.template destroy< animtree_ptr > (); + break; + + case symbol_kind::S_color: // color + value.template destroy< color_ptr > (); + break; + + case symbol_kind::S_constant: // constant + value.template destroy< constant_ptr > (); + break; + + case symbol_kind::S_define: // define + value.template destroy< define_ptr > (); + break; + + case symbol_kind::S_empty_array: // empty_array + value.template destroy< empty_array_ptr > (); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.template destroy< expr_arguments_ptr > (); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.template destroy< expr_assign_ptr > (); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.template destroy< expr_call_ptr > (); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.template destroy< expr_call_type_ptr > (); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.template destroy< expr_ptr > (); + break; + + case symbol_kind::S_false: // false + value.template destroy< false_ptr > (); + break; + + case symbol_kind::S_file: // file + value.template destroy< file_ptr > (); + break; + + case symbol_kind::S_float: // float + value.template destroy< float_ptr > (); + break; + + case symbol_kind::S_game: // game + value.template destroy< game_ptr > (); + break; + + case symbol_kind::S_include: // include + value.template destroy< include_ptr > (); + break; + + case symbol_kind::S_integer: // integer + value.template destroy< integer_ptr > (); + break; + + case symbol_kind::S_istring: // istring + value.template destroy< istring_ptr > (); + break; + + case symbol_kind::S_level: // level + value.template destroy< level_ptr > (); + break; + + case symbol_kind::S_name: // name + value.template destroy< name_ptr > (); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.template destroy< node_ptr > (); + break; + + case symbol_kind::S_parameters: // parameters + value.template destroy< parameters_ptr > (); + break; + + case symbol_kind::S_program: // program + value.template destroy< program_ptr > (); + break; + + case symbol_kind::S_self: // self + value.template destroy< self_ptr > (); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.template destroy< std::string > (); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.template destroy< stmt_assign_ptr > (); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.template destroy< stmt_break_ptr > (); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.template destroy< stmt_call_ptr > (); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.template destroy< stmt_case_ptr > (); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.template destroy< stmt_continue_ptr > (); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.template destroy< stmt_default_ptr > (); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.template destroy< stmt_endon_ptr > (); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.template destroy< stmt_for_ptr > (); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.template destroy< stmt_foreach_ptr > (); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.template destroy< stmt_if_ptr > (); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.template destroy< stmt_ifelse_ptr > (); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.template destroy< stmt_list_ptr > (); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.template destroy< stmt_notify_ptr > (); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.template destroy< stmt_ptr > (); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.template destroy< stmt_return_ptr > (); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.template destroy< stmt_switch_ptr > (); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.template destroy< stmt_wait_ptr > (); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.template destroy< stmt_waitframe_ptr > (); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.template destroy< stmt_waittill_ptr > (); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.template destroy< stmt_waittillframeend_ptr > (); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.template destroy< stmt_waittillmatch_ptr > (); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.template destroy< stmt_while_ptr > (); + break; + + case symbol_kind::S_string: // string + value.template destroy< string_ptr > (); + break; + + case symbol_kind::S_thisthread: // thisthread + value.template destroy< thisthread_ptr > (); + break; + + case symbol_kind::S_thread: // thread + value.template destroy< thread_ptr > (); + break; + + case symbol_kind::S_true: // true + value.template destroy< true_ptr > (); + break; + + case symbol_kind::S_undefined: // undefined + value.template destroy< undefined_ptr > (); + break; + + case symbol_kind::S_usingtree: // usingtree + value.template destroy< usingtree_ptr > (); + break; + + case symbol_kind::S_vector: // vector + value.template destroy< vector_ptr > (); + break; + + default: + break; + } + + Base::clear (); + } + + /// The user-facing name of this symbol. + const char *name () const YY_NOEXCEPT + { + return parser::symbol_name (this->kind ()); + } + + /// Backward compatibility (Bison 3.6). + symbol_kind_type type_get () const YY_NOEXCEPT; + + /// Whether empty. + bool empty () const YY_NOEXCEPT; + + /// Destructive move, \a s is emptied into this. + void move (basic_symbol& s); + + /// The semantic value. + semantic_type value; + + /// The location. + location_type location; + + private: +#if YY_CPLUSPLUS < 201103L + /// Assignment operator. + basic_symbol& operator= (const basic_symbol& that); +#endif + }; + + /// Type access provider for token (enum) based symbols. + struct by_kind + { + /// Default constructor. + by_kind (); + +#if 201103L <= YY_CPLUSPLUS + /// Move constructor. + by_kind (by_kind&& that); +#endif + + /// Copy constructor. + by_kind (const by_kind& that); + + /// The symbol kind as needed by the constructor. + typedef token_kind_type kind_type; + + /// Constructor from (external) token numbers. + by_kind (kind_type t); + + /// Record that this symbol is empty. + void clear () YY_NOEXCEPT; + + /// Steal the symbol kind from \a that. + void move (by_kind& that); + + /// The (internal) type number (corresponding to \a type). + /// \a empty when empty. + symbol_kind_type kind () const YY_NOEXCEPT; + + /// Backward compatibility (Bison 3.6). + symbol_kind_type type_get () const YY_NOEXCEPT; + + /// The symbol kind. + /// \a S_YYEMPTY when empty. + symbol_kind_type kind_; + }; + + /// Backward compatibility for a private implementation detail (Bison 3.6). + typedef by_kind by_type; + + /// "External" symbols: returned by the scanner. + struct symbol_type : basic_symbol + { + /// Superclass. + typedef basic_symbol super_type; + + /// Empty symbol. + symbol_type () {} + + /// Constructor for valueless symbols, and symbols from each type. +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, location_type l) + : super_type(token_type (tok), std::move (l)) +#else + symbol_type (int tok, const location_type& l) + : super_type(token_type (tok), l) +#endif + { + S4_ASSERT (tok == token::S4EOF + || (token::S4error <= tok && tok <= token::MOD) + || (token::ADD_ARRAY <= tok && tok <= token::POSTDEC)); + } +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, std::string v, location_type l) + : super_type(token_type (tok), std::move (v), std::move (l)) +#else + symbol_type (int tok, const std::string& v, const location_type& l) + : super_type(token_type (tok), v, l) +#endif + { + S4_ASSERT ((token::FILE <= tok && tok <= token::INT_HEX)); + } + }; + + /// Build a parser object. + parser (yyscan_t yyscanner_yyarg, xsk::gsc::location& loc_yyarg, xsk::gsc::program_ptr& ast_yyarg); + virtual ~parser (); + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + parser (const parser&) = delete; + /// Non copyable. + parser& operator= (const parser&) = delete; +#endif + + /// Parse. An alias for parse (). + /// \returns 0 iff parsing succeeded. + int operator() (); + + /// Parse. + /// \returns 0 iff parsing succeeded. + virtual int parse (); + +#if S4DEBUG + /// The current debugging stream. + std::ostream& debug_stream () const YY_ATTRIBUTE_PURE; + /// Set the current debugging stream. + void set_debug_stream (std::ostream &); + + /// Type for debugging levels. + typedef int debug_level_type; + /// The current debugging level. + debug_level_type debug_level () const YY_ATTRIBUTE_PURE; + /// Set the current debugging level. + void set_debug_level (debug_level_type l); +#endif + + /// Report a syntax error. + /// \param loc where the syntax error is found. + /// \param msg a description of the syntax error. + virtual void error (const location_type& loc, const std::string& msg); + + /// Report a syntax error. + void error (const syntax_error& err); + + /// The user-facing name of the symbol whose (internal) number is + /// YYSYMBOL. No bounds checking. + static const char *symbol_name (symbol_kind_type yysymbol); + + // Implementation of make_symbol for each symbol type. +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_S4EOF (location_type l) + { + return symbol_type (token::S4EOF, std::move (l)); + } +#else + static + symbol_type + make_S4EOF (const location_type& l) + { + return symbol_type (token::S4EOF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_S4error (location_type l) + { + return symbol_type (token::S4error, std::move (l)); + } +#else + static + symbol_type + make_S4error (const location_type& l) + { + return symbol_type (token::S4error, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_S4UNDEF (location_type l) + { + return symbol_type (token::S4UNDEF, std::move (l)); + } +#else + static + symbol_type + make_S4UNDEF (const location_type& l) + { + return symbol_type (token::S4UNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INCLUDE (location_type l) + { + return symbol_type (token::INCLUDE, std::move (l)); + } +#else + static + symbol_type + make_INCLUDE (const location_type& l) + { + return symbol_type (token::INCLUDE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_USINGTREE (location_type l) + { + return symbol_type (token::USINGTREE, std::move (l)); + } +#else + static + symbol_type + make_USINGTREE (const location_type& l) + { + return symbol_type (token::USINGTREE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ANIMTREE (location_type l) + { + return symbol_type (token::ANIMTREE, std::move (l)); + } +#else + static + symbol_type + make_ANIMTREE (const location_type& l) + { + return symbol_type (token::ANIMTREE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ENDON (location_type l) + { + return symbol_type (token::ENDON, std::move (l)); + } +#else + static + symbol_type + make_ENDON (const location_type& l) + { + return symbol_type (token::ENDON, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NOTIFY (location_type l) + { + return symbol_type (token::NOTIFY, std::move (l)); + } +#else + static + symbol_type + make_NOTIFY (const location_type& l) + { + return symbol_type (token::NOTIFY, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WAIT (location_type l) + { + return symbol_type (token::WAIT, std::move (l)); + } +#else + static + symbol_type + make_WAIT (const location_type& l) + { + return symbol_type (token::WAIT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WAITTILL (location_type l) + { + return symbol_type (token::WAITTILL, std::move (l)); + } +#else + static + symbol_type + make_WAITTILL (const location_type& l) + { + return symbol_type (token::WAITTILL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WAITTILLMATCH (location_type l) + { + return symbol_type (token::WAITTILLMATCH, std::move (l)); + } +#else + static + symbol_type + make_WAITTILLMATCH (const location_type& l) + { + return symbol_type (token::WAITTILLMATCH, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WAITTILLFRAMEEND (location_type l) + { + return symbol_type (token::WAITTILLFRAMEEND, std::move (l)); + } +#else + static + symbol_type + make_WAITTILLFRAMEEND (const location_type& l) + { + return symbol_type (token::WAITTILLFRAMEEND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WAITFRAME (location_type l) + { + return symbol_type (token::WAITFRAME, std::move (l)); + } +#else + static + symbol_type + make_WAITFRAME (const location_type& l) + { + return symbol_type (token::WAITFRAME, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IF (location_type l) + { + return symbol_type (token::IF, std::move (l)); + } +#else + static + symbol_type + make_IF (const location_type& l) + { + return symbol_type (token::IF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ELSE (location_type l) + { + return symbol_type (token::ELSE, std::move (l)); + } +#else + static + symbol_type + make_ELSE (const location_type& l) + { + return symbol_type (token::ELSE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WHILE (location_type l) + { + return symbol_type (token::WHILE, std::move (l)); + } +#else + static + symbol_type + make_WHILE (const location_type& l) + { + return symbol_type (token::WHILE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FOR (location_type l) + { + return symbol_type (token::FOR, std::move (l)); + } +#else + static + symbol_type + make_FOR (const location_type& l) + { + return symbol_type (token::FOR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FOREACH (location_type l) + { + return symbol_type (token::FOREACH, std::move (l)); + } +#else + static + symbol_type + make_FOREACH (const location_type& l) + { + return symbol_type (token::FOREACH, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IN (location_type l) + { + return symbol_type (token::IN, std::move (l)); + } +#else + static + symbol_type + make_IN (const location_type& l) + { + return symbol_type (token::IN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SWITCH (location_type l) + { + return symbol_type (token::SWITCH, std::move (l)); + } +#else + static + symbol_type + make_SWITCH (const location_type& l) + { + return symbol_type (token::SWITCH, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CASE (location_type l) + { + return symbol_type (token::CASE, std::move (l)); + } +#else + static + symbol_type + make_CASE (const location_type& l) + { + return symbol_type (token::CASE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEFAULT (location_type l) + { + return symbol_type (token::DEFAULT, std::move (l)); + } +#else + static + symbol_type + make_DEFAULT (const location_type& l) + { + return symbol_type (token::DEFAULT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BREAK (location_type l) + { + return symbol_type (token::BREAK, std::move (l)); + } +#else + static + symbol_type + make_BREAK (const location_type& l) + { + return symbol_type (token::BREAK, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CONTINUE (location_type l) + { + return symbol_type (token::CONTINUE, std::move (l)); + } +#else + static + symbol_type + make_CONTINUE (const location_type& l) + { + return symbol_type (token::CONTINUE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RETURN (location_type l) + { + return symbol_type (token::RETURN, std::move (l)); + } +#else + static + symbol_type + make_RETURN (const location_type& l) + { + return symbol_type (token::RETURN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_THREAD (location_type l) + { + return symbol_type (token::THREAD, std::move (l)); + } +#else + static + symbol_type + make_THREAD (const location_type& l) + { + return symbol_type (token::THREAD, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CHILDTHREAD (location_type l) + { + return symbol_type (token::CHILDTHREAD, std::move (l)); + } +#else + static + symbol_type + make_CHILDTHREAD (const location_type& l) + { + return symbol_type (token::CHILDTHREAD, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_THISTHREAD (location_type l) + { + return symbol_type (token::THISTHREAD, std::move (l)); + } +#else + static + symbol_type + make_THISTHREAD (const location_type& l) + { + return symbol_type (token::THISTHREAD, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CALL (location_type l) + { + return symbol_type (token::CALL, std::move (l)); + } +#else + static + symbol_type + make_CALL (const location_type& l) + { + return symbol_type (token::CALL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_TRUE (location_type l) + { + return symbol_type (token::TRUE, std::move (l)); + } +#else + static + symbol_type + make_TRUE (const location_type& l) + { + return symbol_type (token::TRUE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FALSE (location_type l) + { + return symbol_type (token::FALSE, std::move (l)); + } +#else + static + symbol_type + make_FALSE (const location_type& l) + { + return symbol_type (token::FALSE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_UNDEFINED (location_type l) + { + return symbol_type (token::UNDEFINED, std::move (l)); + } +#else + static + symbol_type + make_UNDEFINED (const location_type& l) + { + return symbol_type (token::UNDEFINED, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SIZE (location_type l) + { + return symbol_type (token::SIZE, std::move (l)); + } +#else + static + symbol_type + make_SIZE (const location_type& l) + { + return symbol_type (token::SIZE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_GAME (location_type l) + { + return symbol_type (token::GAME, std::move (l)); + } +#else + static + symbol_type + make_GAME (const location_type& l) + { + return symbol_type (token::GAME, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SELF (location_type l) + { + return symbol_type (token::SELF, std::move (l)); + } +#else + static + symbol_type + make_SELF (const location_type& l) + { + return symbol_type (token::SELF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ANIM (location_type l) + { + return symbol_type (token::ANIM, std::move (l)); + } +#else + static + symbol_type + make_ANIM (const location_type& l) + { + return symbol_type (token::ANIM, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LEVEL (location_type l) + { + return symbol_type (token::LEVEL, std::move (l)); + } +#else + static + symbol_type + make_LEVEL (const location_type& l) + { + return symbol_type (token::LEVEL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LPAREN (location_type l) + { + return symbol_type (token::LPAREN, std::move (l)); + } +#else + static + symbol_type + make_LPAREN (const location_type& l) + { + return symbol_type (token::LPAREN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RPAREN (location_type l) + { + return symbol_type (token::RPAREN, std::move (l)); + } +#else + static + symbol_type + make_RPAREN (const location_type& l) + { + return symbol_type (token::RPAREN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LBRACE (location_type l) + { + return symbol_type (token::LBRACE, std::move (l)); + } +#else + static + symbol_type + make_LBRACE (const location_type& l) + { + return symbol_type (token::LBRACE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RBRACE (location_type l) + { + return symbol_type (token::RBRACE, std::move (l)); + } +#else + static + symbol_type + make_RBRACE (const location_type& l) + { + return symbol_type (token::RBRACE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LBRACKET (location_type l) + { + return symbol_type (token::LBRACKET, std::move (l)); + } +#else + static + symbol_type + make_LBRACKET (const location_type& l) + { + return symbol_type (token::LBRACKET, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RBRACKET (location_type l) + { + return symbol_type (token::RBRACKET, std::move (l)); + } +#else + static + symbol_type + make_RBRACKET (const location_type& l) + { + return symbol_type (token::RBRACKET, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_COMMA (location_type l) + { + return symbol_type (token::COMMA, std::move (l)); + } +#else + static + symbol_type + make_COMMA (const location_type& l) + { + return symbol_type (token::COMMA, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DOT (location_type l) + { + return symbol_type (token::DOT, std::move (l)); + } +#else + static + symbol_type + make_DOT (const location_type& l) + { + return symbol_type (token::DOT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DOUBLECOLON (location_type l) + { + return symbol_type (token::DOUBLECOLON, std::move (l)); + } +#else + static + symbol_type + make_DOUBLECOLON (const location_type& l) + { + return symbol_type (token::DOUBLECOLON, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_COLON (location_type l) + { + return symbol_type (token::COLON, std::move (l)); + } +#else + static + symbol_type + make_COLON (const location_type& l) + { + return symbol_type (token::COLON, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SEMICOLON (location_type l) + { + return symbol_type (token::SEMICOLON, std::move (l)); + } +#else + static + symbol_type + make_SEMICOLON (const location_type& l) + { + return symbol_type (token::SEMICOLON, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_QMARK (location_type l) + { + return symbol_type (token::QMARK, std::move (l)); + } +#else + static + symbol_type + make_QMARK (const location_type& l) + { + return symbol_type (token::QMARK, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INCREMENT (location_type l) + { + return symbol_type (token::INCREMENT, std::move (l)); + } +#else + static + symbol_type + make_INCREMENT (const location_type& l) + { + return symbol_type (token::INCREMENT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DECREMENT (location_type l) + { + return symbol_type (token::DECREMENT, std::move (l)); + } +#else + static + symbol_type + make_DECREMENT (const location_type& l) + { + return symbol_type (token::DECREMENT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LSHIFT (location_type l) + { + return symbol_type (token::LSHIFT, std::move (l)); + } +#else + static + symbol_type + make_LSHIFT (const location_type& l) + { + return symbol_type (token::LSHIFT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RSHIFT (location_type l) + { + return symbol_type (token::RSHIFT, std::move (l)); + } +#else + static + symbol_type + make_RSHIFT (const location_type& l) + { + return symbol_type (token::RSHIFT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_OR (location_type l) + { + return symbol_type (token::OR, std::move (l)); + } +#else + static + symbol_type + make_OR (const location_type& l) + { + return symbol_type (token::OR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_AND (location_type l) + { + return symbol_type (token::AND, std::move (l)); + } +#else + static + symbol_type + make_AND (const location_type& l) + { + return symbol_type (token::AND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_EQUALITY (location_type l) + { + return symbol_type (token::EQUALITY, std::move (l)); + } +#else + static + symbol_type + make_EQUALITY (const location_type& l) + { + return symbol_type (token::EQUALITY, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INEQUALITY (location_type l) + { + return symbol_type (token::INEQUALITY, std::move (l)); + } +#else + static + symbol_type + make_INEQUALITY (const location_type& l) + { + return symbol_type (token::INEQUALITY, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LESS_EQUAL (location_type l) + { + return symbol_type (token::LESS_EQUAL, std::move (l)); + } +#else + static + symbol_type + make_LESS_EQUAL (const location_type& l) + { + return symbol_type (token::LESS_EQUAL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_GREATER_EQUAL (location_type l) + { + return symbol_type (token::GREATER_EQUAL, std::move (l)); + } +#else + static + symbol_type + make_GREATER_EQUAL (const location_type& l) + { + return symbol_type (token::GREATER_EQUAL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LESS (location_type l) + { + return symbol_type (token::LESS, std::move (l)); + } +#else + static + symbol_type + make_LESS (const location_type& l) + { + return symbol_type (token::LESS, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_GREATER (location_type l) + { + return symbol_type (token::GREATER, std::move (l)); + } +#else + static + symbol_type + make_GREATER (const location_type& l) + { + return symbol_type (token::GREATER, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NOT (location_type l) + { + return symbol_type (token::NOT, std::move (l)); + } +#else + static + symbol_type + make_NOT (const location_type& l) + { + return symbol_type (token::NOT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_COMPLEMENT (location_type l) + { + return symbol_type (token::COMPLEMENT, std::move (l)); + } +#else + static + symbol_type + make_COMPLEMENT (const location_type& l) + { + return symbol_type (token::COMPLEMENT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN (location_type l) + { + return symbol_type (token::ASSIGN, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN (const location_type& l) + { + return symbol_type (token::ASSIGN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_ADD (location_type l) + { + return symbol_type (token::ASSIGN_ADD, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_ADD (const location_type& l) + { + return symbol_type (token::ASSIGN_ADD, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_SUB (location_type l) + { + return symbol_type (token::ASSIGN_SUB, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_SUB (const location_type& l) + { + return symbol_type (token::ASSIGN_SUB, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_MULT (location_type l) + { + return symbol_type (token::ASSIGN_MULT, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_MULT (const location_type& l) + { + return symbol_type (token::ASSIGN_MULT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_DIV (location_type l) + { + return symbol_type (token::ASSIGN_DIV, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_DIV (const location_type& l) + { + return symbol_type (token::ASSIGN_DIV, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_MOD (location_type l) + { + return symbol_type (token::ASSIGN_MOD, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_MOD (const location_type& l) + { + return symbol_type (token::ASSIGN_MOD, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_BITWISE_OR (location_type l) + { + return symbol_type (token::ASSIGN_BITWISE_OR, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BITWISE_OR (const location_type& l) + { + return symbol_type (token::ASSIGN_BITWISE_OR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_BITWISE_AND (location_type l) + { + return symbol_type (token::ASSIGN_BITWISE_AND, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BITWISE_AND (const location_type& l) + { + return symbol_type (token::ASSIGN_BITWISE_AND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_BITWISE_EXOR (location_type l) + { + return symbol_type (token::ASSIGN_BITWISE_EXOR, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BITWISE_EXOR (const location_type& l) + { + return symbol_type (token::ASSIGN_BITWISE_EXOR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_RSHIFT (location_type l) + { + return symbol_type (token::ASSIGN_RSHIFT, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_RSHIFT (const location_type& l) + { + return symbol_type (token::ASSIGN_RSHIFT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_LSHIFT (location_type l) + { + return symbol_type (token::ASSIGN_LSHIFT, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_LSHIFT (const location_type& l) + { + return symbol_type (token::ASSIGN_LSHIFT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BITWISE_OR (location_type l) + { + return symbol_type (token::BITWISE_OR, std::move (l)); + } +#else + static + symbol_type + make_BITWISE_OR (const location_type& l) + { + return symbol_type (token::BITWISE_OR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BITWISE_AND (location_type l) + { + return symbol_type (token::BITWISE_AND, std::move (l)); + } +#else + static + symbol_type + make_BITWISE_AND (const location_type& l) + { + return symbol_type (token::BITWISE_AND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BITWISE_EXOR (location_type l) + { + return symbol_type (token::BITWISE_EXOR, std::move (l)); + } +#else + static + symbol_type + make_BITWISE_EXOR (const location_type& l) + { + return symbol_type (token::BITWISE_EXOR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ADD (location_type l) + { + return symbol_type (token::ADD, std::move (l)); + } +#else + static + symbol_type + make_ADD (const location_type& l) + { + return symbol_type (token::ADD, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SUB (location_type l) + { + return symbol_type (token::SUB, std::move (l)); + } +#else + static + symbol_type + make_SUB (const location_type& l) + { + return symbol_type (token::SUB, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_MULT (location_type l) + { + return symbol_type (token::MULT, std::move (l)); + } +#else + static + symbol_type + make_MULT (const location_type& l) + { + return symbol_type (token::MULT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DIV (location_type l) + { + return symbol_type (token::DIV, std::move (l)); + } +#else + static + symbol_type + make_DIV (const location_type& l) + { + return symbol_type (token::DIV, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_MOD (location_type l) + { + return symbol_type (token::MOD, std::move (l)); + } +#else + static + symbol_type + make_MOD (const location_type& l) + { + return symbol_type (token::MOD, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FILE (std::string v, location_type l) + { + return symbol_type (token::FILE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FILE (const std::string& v, const location_type& l) + { + return symbol_type (token::FILE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NAME (std::string v, location_type l) + { + return symbol_type (token::NAME, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_NAME (const std::string& v, const location_type& l) + { + return symbol_type (token::NAME, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_STRING (std::string v, location_type l) + { + return symbol_type (token::STRING, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_STRING (const std::string& v, const location_type& l) + { + return symbol_type (token::STRING, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ISTRING (std::string v, location_type l) + { + return symbol_type (token::ISTRING, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ISTRING (const std::string& v, const location_type& l) + { + return symbol_type (token::ISTRING, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_COLOR (std::string v, location_type l) + { + return symbol_type (token::COLOR, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_COLOR (const std::string& v, const location_type& l) + { + return symbol_type (token::COLOR, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FLOAT (std::string v, location_type l) + { + return symbol_type (token::FLOAT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FLOAT (const std::string& v, const location_type& l) + { + return symbol_type (token::FLOAT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INT_DEC (std::string v, location_type l) + { + return symbol_type (token::INT_DEC, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INT_DEC (const std::string& v, const location_type& l) + { + return symbol_type (token::INT_DEC, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INT_OCT (std::string v, location_type l) + { + return symbol_type (token::INT_OCT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INT_OCT (const std::string& v, const location_type& l) + { + return symbol_type (token::INT_OCT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INT_BIN (std::string v, location_type l) + { + return symbol_type (token::INT_BIN, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INT_BIN (const std::string& v, const location_type& l) + { + return symbol_type (token::INT_BIN, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INT_HEX (std::string v, location_type l) + { + return symbol_type (token::INT_HEX, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INT_HEX (const std::string& v, const location_type& l) + { + return symbol_type (token::INT_HEX, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ADD_ARRAY (location_type l) + { + return symbol_type (token::ADD_ARRAY, std::move (l)); + } +#else + static + symbol_type + make_ADD_ARRAY (const location_type& l) + { + return symbol_type (token::ADD_ARRAY, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_THEN (location_type l) + { + return symbol_type (token::THEN, std::move (l)); + } +#else + static + symbol_type + make_THEN (const location_type& l) + { + return symbol_type (token::THEN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_TERN (location_type l) + { + return symbol_type (token::TERN, std::move (l)); + } +#else + static + symbol_type + make_TERN (const location_type& l) + { + return symbol_type (token::TERN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NEG (location_type l) + { + return symbol_type (token::NEG, std::move (l)); + } +#else + static + symbol_type + make_NEG (const location_type& l) + { + return symbol_type (token::NEG, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ANIMREF (location_type l) + { + return symbol_type (token::ANIMREF, std::move (l)); + } +#else + static + symbol_type + make_ANIMREF (const location_type& l) + { + return symbol_type (token::ANIMREF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PREINC (location_type l) + { + return symbol_type (token::PREINC, std::move (l)); + } +#else + static + symbol_type + make_PREINC (const location_type& l) + { + return symbol_type (token::PREINC, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PREDEC (location_type l) + { + return symbol_type (token::PREDEC, std::move (l)); + } +#else + static + symbol_type + make_PREDEC (const location_type& l) + { + return symbol_type (token::PREDEC, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_POSTINC (location_type l) + { + return symbol_type (token::POSTINC, std::move (l)); + } +#else + static + symbol_type + make_POSTINC (const location_type& l) + { + return symbol_type (token::POSTINC, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_POSTDEC (location_type l) + { + return symbol_type (token::POSTDEC, std::move (l)); + } +#else + static + symbol_type + make_POSTDEC (const location_type& l) + { + return symbol_type (token::POSTDEC, l); + } +#endif + + + class context + { + public: + context (const parser& yyparser, const symbol_type& yyla); + const symbol_type& lookahead () const YY_NOEXCEPT { return yyla_; } + symbol_kind_type token () const YY_NOEXCEPT { return yyla_.kind (); } + const location_type& location () const YY_NOEXCEPT { return yyla_.location; } + + /// Put in YYARG at most YYARGN of the expected tokens, and return the + /// number of tokens stored in YYARG. If YYARG is null, return the + /// number of expected tokens (guaranteed to be less than YYNTOKENS). + int expected_tokens (symbol_kind_type yyarg[], int yyargn) const; + + private: + const parser& yyparser_; + const symbol_type& yyla_; + }; + + private: +#if YY_CPLUSPLUS < 201103L + /// Non copyable. + parser (const parser&); + /// Non copyable. + parser& operator= (const parser&); +#endif + + /// Check the lookahead yytoken. + /// \returns true iff the token will be eventually shifted. + bool yy_lac_check_ (symbol_kind_type yytoken) const; + /// Establish the initial context if no initial context currently exists. + /// \returns true iff the token will be eventually shifted. + bool yy_lac_establish_ (symbol_kind_type yytoken); + /// Discard any previous initial lookahead context because of event. + /// \param event the event which caused the lookahead to be discarded. + /// Only used for debbuging output. + void yy_lac_discard_ (const char* event); + + /// Stored state numbers (used for stacks). + typedef short state_type; + + /// The arguments of the error message. + int yy_syntax_error_arguments_ (const context& yyctx, + symbol_kind_type yyarg[], int yyargn) const; + + /// Generate an error message. + /// \param yyctx the context in which the error occurred. + virtual std::string yysyntax_error_ (const context& yyctx) const; + /// Compute post-reduction state. + /// \param yystate the current state + /// \param yysym the nonterminal to push on the stack + static state_type yy_lr_goto_state_ (state_type yystate, int yysym); + + /// Whether the given \c yypact_ value indicates a defaulted state. + /// \param yyvalue the value to check + static bool yy_pact_value_is_default_ (int yyvalue); + + /// Whether the given \c yytable_ value indicates a syntax error. + /// \param yyvalue the value to check + static bool yy_table_value_is_error_ (int yyvalue); + + static const short yypact_ninf_; + static const short yytable_ninf_; + + /// Convert a scanner token kind \a t to a symbol kind. + /// In theory \a t should be a token_kind_type, but character literals + /// are valid, yet not members of the token_type enum. + static symbol_kind_type yytranslate_ (int t); + + + + // Tables. + // YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + // STATE-NUM. + static const short yypact_[]; + + // YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + // Performed when YYTABLE does not specify something else to do. Zero + // means the default is an error. + static const unsigned char yydefact_[]; + + // YYPGOTO[NTERM-NUM]. + static const short yypgoto_[]; + + // YYDEFGOTO[NTERM-NUM]. + static const short yydefgoto_[]; + + // YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + // positive, shift that token. If negative, reduce the rule whose + // number is the opposite. If YYTABLE_NINF, syntax error. + static const short yytable_[]; + + static const short yycheck_[]; + + // YYSTOS[STATE-NUM] -- The (internal number of the) accessing + // symbol of state STATE-NUM. + static const unsigned char yystos_[]; + + // YYR1[YYN] -- Symbol number of symbol that rule YYN derives. + static const unsigned char yyr1_[]; + + // YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. + static const signed char yyr2_[]; + + +#if S4DEBUG + // YYRLINE[YYN] -- Source line where rule number YYN was defined. + static const short yyrline_[]; + /// Report on the debug stream that the rule \a r is going to be reduced. + virtual void yy_reduce_print_ (int r) const; + /// Print the state stack on the debug stream. + virtual void yy_stack_print_ () const; + + /// Debugging level. + int yydebug_; + /// Debug stream. + std::ostream* yycdebug_; + + /// \brief Display a symbol kind, value and location. + /// \param yyo The output stream. + /// \param yysym The symbol. + template + void yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const; +#endif + + /// \brief Reclaim the memory associated to a symbol. + /// \param yymsg Why this token is reclaimed. + /// If null, print nothing. + /// \param yysym The symbol. + template + void yy_destroy_ (const char* yymsg, basic_symbol& yysym) const; + + private: + /// Type access provider for state based symbols. + struct by_state + { + /// Default constructor. + by_state () YY_NOEXCEPT; + + /// The symbol kind as needed by the constructor. + typedef state_type kind_type; + + /// Constructor. + by_state (kind_type s) YY_NOEXCEPT; + + /// Copy constructor. + by_state (const by_state& that) YY_NOEXCEPT; + + /// Record that this symbol is empty. + void clear () YY_NOEXCEPT; + + /// Steal the symbol kind from \a that. + void move (by_state& that); + + /// The symbol kind (corresponding to \a state). + /// \a symbol_kind::S_YYEMPTY when empty. + symbol_kind_type kind () const YY_NOEXCEPT; + + /// The state number used to denote an empty symbol. + /// We use the initial state, as it does not have a value. + enum { empty_state = 0 }; + + /// The state. + /// \a empty when empty. + state_type state; + }; + + /// "Internal" symbol: element of the stack. + struct stack_symbol_type : basic_symbol + { + /// Superclass. + typedef basic_symbol super_type; + /// Construct an empty symbol. + stack_symbol_type (); + /// Move or copy construction. + stack_symbol_type (YY_RVREF (stack_symbol_type) that); + /// Steal the contents from \a sym to build this. + stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) sym); +#if YY_CPLUSPLUS < 201103L + /// Assignment, needed by push_back by some old implementations. + /// Moves the contents of that. + stack_symbol_type& operator= (stack_symbol_type& that); + + /// Assignment, needed by push_back by other implementations. + /// Needed by some other old implementations. + stack_symbol_type& operator= (const stack_symbol_type& that); +#endif + }; + + /// A stack with random access from its top. + template > + class stack + { + public: + // Hide our reversed order. + typedef typename S::iterator iterator; + typedef typename S::const_iterator const_iterator; + typedef typename S::size_type size_type; + typedef typename std::ptrdiff_t index_type; + + stack (size_type n = 200) + : seq_ (n) + {} + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + stack (const stack&) = delete; + /// Non copyable. + stack& operator= (const stack&) = delete; +#endif + + /// Random access. + /// + /// Index 0 returns the topmost element. + const T& + operator[] (index_type i) const + { + return seq_[size_type (size () - 1 - i)]; + } + + /// Random access. + /// + /// Index 0 returns the topmost element. + T& + operator[] (index_type i) + { + return seq_[size_type (size () - 1 - i)]; + } + + /// Steal the contents of \a t. + /// + /// Close to move-semantics. + void + push (YY_MOVE_REF (T) t) + { + seq_.push_back (T ()); + operator[] (0).move (t); + } + + /// Pop elements from the stack. + void + pop (std::ptrdiff_t n = 1) YY_NOEXCEPT + { + for (; 0 < n; --n) + seq_.pop_back (); + } + + /// Pop all elements from the stack. + void + clear () YY_NOEXCEPT + { + seq_.clear (); + } + + /// Number of elements on the stack. + index_type + size () const YY_NOEXCEPT + { + return index_type (seq_.size ()); + } + + /// Iterator on top of the stack (going downwards). + const_iterator + begin () const YY_NOEXCEPT + { + return seq_.begin (); + } + + /// Bottom of the stack. + const_iterator + end () const YY_NOEXCEPT + { + return seq_.end (); + } + + /// Present a slice of the top of a stack. + class slice + { + public: + slice (const stack& stack, index_type range) + : stack_ (stack) + , range_ (range) + {} + + const T& + operator[] (index_type i) const + { + return stack_[range_ - i]; + } + + private: + const stack& stack_; + index_type range_; + }; + + private: +#if YY_CPLUSPLUS < 201103L + /// Non copyable. + stack (const stack&); + /// Non copyable. + stack& operator= (const stack&); +#endif + /// The wrapped container. + S seq_; + }; + + + /// Stack type. + typedef stack stack_type; + + /// The stack. + stack_type yystack_; + /// The stack for LAC. + /// Logically, the yy_lac_stack's lifetime is confined to the function + /// yy_lac_check_. We just store it as a member of this class to hold + /// on to the memory and to avoid frequent reallocations. + /// Since yy_lac_check_ is const, this member must be mutable. + mutable std::vector yylac_stack_; + /// Whether an initial LAC context was established. + bool yy_lac_established_; + + + /// Push a new state on the stack. + /// \param m a debug message to display + /// if null, no trace is output. + /// \param sym the symbol + /// \warning the contents of \a s.value is stolen. + void yypush_ (const char* m, YY_MOVE_REF (stack_symbol_type) sym); + + /// Push a new look ahead token on the state on the stack. + /// \param m a debug message to display + /// if null, no trace is output. + /// \param s the state + /// \param sym the symbol (for its value and location). + /// \warning the contents of \a sym.value is stolen. + void yypush_ (const char* m, state_type s, YY_MOVE_REF (symbol_type) sym); + + /// Pop \a n symbols from the stack. + void yypop_ (int n = 1); + + /// Constants. + enum + { + yylast_ = 1861, ///< Last index in yytable_. + yynnts_ = 73, ///< Number of nonterminal symbols. + yyfinal_ = 15 ///< Termination state number. + }; + + + // User arguments. + yyscan_t yyscanner; + xsk::gsc::location& loc; + xsk::gsc::program_ptr& ast; + + }; + + inline + parser::symbol_kind_type + parser::yytranslate_ (int t) + { + return static_cast (t); + } + + // basic_symbol. + template + parser::basic_symbol::basic_symbol (const basic_symbol& that) + : Base (that) + , value () + , location (that.location) + { + switch (this->kind ()) + { + case symbol_kind::S_anim: // anim + value.copy< anim_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_animation: // animation + value.copy< animation_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_animtree: // animtree + value.copy< animtree_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_color: // color + value.copy< color_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_constant: // constant + value.copy< constant_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_define: // define + value.copy< define_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_empty_array: // empty_array + value.copy< empty_array_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.copy< expr_arguments_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.copy< expr_assign_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.copy< expr_call_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.copy< expr_call_type_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.copy< expr_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_false: // false + value.copy< false_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_file: // file + value.copy< file_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_float: // float + value.copy< float_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_game: // game + value.copy< game_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.copy< include_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_integer: // integer + value.copy< integer_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_istring: // istring + value.copy< istring_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_level: // level + value.copy< level_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_name: // name + value.copy< name_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.copy< node_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_parameters: // parameters + value.copy< parameters_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.copy< program_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_self: // self + value.copy< self_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.copy< std::string > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.copy< stmt_assign_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.copy< stmt_break_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.copy< stmt_call_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.copy< stmt_case_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.copy< stmt_continue_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.copy< stmt_default_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.copy< stmt_endon_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.copy< stmt_for_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.copy< stmt_foreach_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.copy< stmt_if_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.copy< stmt_ifelse_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.copy< stmt_list_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.copy< stmt_notify_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.copy< stmt_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.copy< stmt_return_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.copy< stmt_switch_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.copy< stmt_wait_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.copy< stmt_waitframe_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.copy< stmt_waittill_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.copy< stmt_waittillframeend_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.copy< stmt_waittillmatch_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.copy< stmt_while_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_string: // string + value.copy< string_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_thisthread: // thisthread + value.copy< thisthread_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_thread: // thread + value.copy< thread_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_true: // true + value.copy< true_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_undefined: // undefined + value.copy< undefined_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_usingtree: // usingtree + value.copy< usingtree_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_vector: // vector + value.copy< vector_ptr > (YY_MOVE (that.value)); + break; + + default: + break; + } + + } + + + + template + parser::symbol_kind_type + parser::basic_symbol::type_get () const YY_NOEXCEPT + { + return this->kind (); + } + + template + bool + parser::basic_symbol::empty () const YY_NOEXCEPT + { + return this->kind () == symbol_kind::S_YYEMPTY; + } + + template + void + parser::basic_symbol::move (basic_symbol& s) + { + super_type::move (s); + switch (this->kind ()) + { + case symbol_kind::S_anim: // anim + value.move< anim_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_animation: // animation + value.move< animation_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_animtree: // animtree + value.move< animtree_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_color: // color + value.move< color_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_constant: // constant + value.move< constant_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_define: // define + value.move< define_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_empty_array: // empty_array + value.move< empty_array_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_filled: // expr_arguments_filled + case symbol_kind::S_expr_arguments_empty: // expr_arguments_empty + value.move< expr_arguments_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_assign: // expr_assign + value.move< expr_assign_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + case symbol_kind::S_expr_call_thread: // expr_call_thread + case symbol_kind::S_expr_call_childthread: // expr_call_childthread + value.move< expr_call_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_call_function: // expr_call_function + case symbol_kind::S_expr_call_pointer: // expr_call_pointer + value.move< expr_call_type_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_for_expr: // for_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_compare: // expr_compare + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + value.move< expr_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_false: // false + value.move< false_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_file: // file + value.move< file_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_float: // float + value.move< float_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_game: // game + value.move< game_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_include: // include + value.move< include_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_integer: // integer + value.move< integer_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_istring: // istring + value.move< istring_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_level: // level + value.move< level_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_name: // name + value.move< name_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_function: // expr_function + case symbol_kind::S_expr_add_array: // expr_add_array + case symbol_kind::S_expr_array: // expr_array + case symbol_kind::S_expr_field: // expr_field + case symbol_kind::S_expr_size: // expr_size + case symbol_kind::S_object: // object + value.move< node_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_parameters: // parameters + value.move< parameters_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_program: // program + value.move< program_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_self: // self + value.move< self_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_FILE: // "file path" + case symbol_kind::S_NAME: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_COLOR: // "color" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INT_DEC: // "int" + case symbol_kind::S_INT_OCT: // "octal int" + case symbol_kind::S_INT_BIN: // "binary int" + case symbol_kind::S_INT_HEX: // "hexadecimal int" + value.move< std::string > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< stmt_assign_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< stmt_break_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< stmt_call_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< stmt_case_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< stmt_continue_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< stmt_default_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< stmt_endon_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< stmt_for_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< stmt_foreach_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< stmt_if_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< stmt_ifelse_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_block: // stmt_block + case symbol_kind::S_stmt_list: // stmt_list + value.move< stmt_list_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< stmt_notify_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_for_stmt: // for_stmt + value.move< stmt_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< stmt_return_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< stmt_switch_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< stmt_wait_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< stmt_waitframe_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< stmt_waittill_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< stmt_waittillframeend_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< stmt_waittillmatch_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< stmt_while_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_string: // string + value.move< string_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_thisthread: // thisthread + value.move< thisthread_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_thread: // thread + value.move< thread_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_true: // true + value.move< true_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_undefined: // undefined + value.move< undefined_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_usingtree: // usingtree + value.move< usingtree_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_vector: // vector + value.move< vector_ptr > (YY_MOVE (s.value)); + break; + + default: + break; + } + + location = YY_MOVE (s.location); + } + + // by_kind. + inline + parser::by_kind::by_kind () + : kind_ (symbol_kind::S_YYEMPTY) + {} + +#if 201103L <= YY_CPLUSPLUS + inline + parser::by_kind::by_kind (by_kind&& that) + : kind_ (that.kind_) + { + that.clear (); + } +#endif + + inline + parser::by_kind::by_kind (const by_kind& that) + : kind_ (that.kind_) + {} + + inline + parser::by_kind::by_kind (token_kind_type t) + : kind_ (yytranslate_ (t)) + {} + + inline + void + parser::by_kind::clear () YY_NOEXCEPT + { + kind_ = symbol_kind::S_YYEMPTY; + } + + inline + void + parser::by_kind::move (by_kind& that) + { + kind_ = that.kind_; + that.clear (); + } + + inline + parser::symbol_kind_type + parser::by_kind::kind () const YY_NOEXCEPT + { + return kind_; + } + + inline + parser::symbol_kind_type + parser::by_kind::type_get () const YY_NOEXCEPT + { + return this->kind (); + } + +#line 13 "parser.ypp" +} } } // xsk::gsc::s4 +#line 4914 "parser.hpp" + + + + +#endif // !YY_S4_PARSER_HPP_INCLUDED diff --git a/src/s4/xsk/resolver.cpp b/src/s4/xsk/resolver.cpp new file mode 100644 index 00000000..b66651f2 --- /dev/null +++ b/src/s4/xsk/resolver.cpp @@ -0,0 +1,442 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#include "stdafx.hpp" +#include "s4.hpp" + +namespace xsk::gsc::s4 +{ + +std::unordered_map opcode_map; +std::unordered_map function_map; +std::unordered_map method_map; +std::unordered_map file_map; +std::unordered_map token_map; +std::unordered_map opcode_map_rev; +std::unordered_map function_map_rev; +std::unordered_map method_map_rev; +std::unordered_map file_map_rev; +std::unordered_map token_map_rev; + +auto resolver::opcode_id(const std::string& name) -> std::uint8_t +{ + const auto itr = opcode_map_rev.find(name); + + if (itr != opcode_map_rev.end()) + { + return itr->second; + } + + throw gsc::error(utils::string::va("Couldn't resolve opcode id for name '%s'!", name.data())); +} + +auto resolver::opcode_name(std::uint8_t id) -> std::string +{ + const auto itr = opcode_map.find(id); + + if (itr != opcode_map.end()) + { + return itr->second; + } + + throw gsc::error(utils::string::va("Couldn't resolve opcode name for id '0x%hhX'!", id)); +} + +auto resolver::function_id(const std::string& name) -> std::uint16_t +{ + const auto itr = function_map_rev.find(name); + + if (itr != function_map_rev.end()) + { + return itr->second; + } + + throw gsc::error(utils::string::va("Couldn't resolve builtin function id for name '%s'!", name.data())); +} + +auto resolver::function_name(std::uint16_t id) -> std::string +{ + const auto itr = function_map.find(id); + + if (itr != function_map.end()) + { + return itr->second; + } + + return utils::string::va("_func_%04X", id); +// throw gsc::error(utils::string::va("Couldn't resolve builtin function name for id '%i'!", id)); +} + +auto resolver::method_id(const std::string& name) -> std::uint16_t +{ + const auto itr = method_map_rev.find(name); + + if (itr != method_map_rev.end()) + { + return itr->second; + } + + throw gsc::error(utils::string::va("Couldn't resolve builtin method id for name '%s'!", name.data())); +} + +auto resolver::method_name(std::uint16_t id) -> std::string +{ + const auto itr = method_map.find(id); + + if (itr != method_map.end()) + { + return itr->second; + } + + return utils::string::va("_meth_%04X", id); +// throw gsc::error(utils::string::va("Couldn't resolve builtin method name for id '%i'!", id)); +} + +auto resolver::file_id(const std::string& name) -> std::uint32_t +{ + const auto itr = file_map_rev.find(name); + + if (itr != file_map_rev.end()) + { + return itr->second; + } + + return 0; +} + +auto resolver::file_name(std::uint32_t id) -> std::string +{ + const auto itr = file_map.find(id); + + if (itr != file_map.end()) + { + return itr->second; + } + + return utils::string::va("_ID%i", id); +} + +auto resolver::token_id(const std::string& name) -> std::uint32_t +{ + const auto itr = token_map_rev.find(name); + + if (itr != token_map_rev.end()) + { + return itr->second; + } + + return 0; +} + +auto resolver::token_name(std::uint32_t id) -> std::string +{ + const auto itr = token_map.find(id); + + if (itr != token_map.end()) + { + return itr->second; + } + + return utils::string::va("_ID%i", id); +} + +auto resolver::find_function(const std::string& name) -> bool +{ + const auto itr = function_map_rev.find(name); + + if (itr != function_map_rev.end()) + { + return true; + } + + return false; +} + +auto resolver::find_method(const std::string& name) -> bool +{ + const auto itr = method_map_rev.find(name); + + if (itr != method_map_rev.end()) + { + return true; + } + + return false; +} + +const std::array opcode_list +{{ + { std::uint8_t(opcode::OP_CastFieldObject), "CAST_FIELD_OBJECT" }, + { std::uint8_t(opcode::OP_SetLocalVariableFieldCached), "SET_LOCAL_VARIABLE_FIELD_CACHED" }, + { std::uint8_t(opcode::OP_plus), "PLUS" }, + { std::uint8_t(opcode::OP_RemoveLocalVariables), "REMOVE_LOCAL_VARIABLES" }, + { std::uint8_t(opcode::OP_EvalSelfFieldVariableRef), "EVAL_SELF_FIELD_VARIABLE_REF" }, + { std::uint8_t(opcode::OP_ScriptFarMethodChildThreadCall), "SCRIPT_FAR_METHOD_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_GetGameRef), "GET_GAME_REF" }, + { std::uint8_t(opcode::OP_EvalAnimFieldVariable), "EVAL_ANIM_FIELD_VARIABLE" }, + { std::uint8_t(opcode::OP_EvalLevelFieldVariableRef), "EVAL_LEVEL_FIELD_VARIABLE_REF" }, + { std::uint8_t(opcode::OP_GetThisthread), "GET_THISTHREAD" }, + { std::uint8_t(opcode::OP_greater), "GREATER" }, + { std::uint8_t(opcode::OP_waittillmatch), "WAITTILLMATCH" }, + { std::uint8_t(opcode::OP_shift_right), "SHIFT_RIGHT" }, + { std::uint8_t(opcode::OP_dec), "DECREMENT" }, + { std::uint8_t(opcode::OP_JumpOnTrue), "JUMP_ON_TRUE" }, + { std::uint8_t(opcode::OP_bit_or), "BIT_OR" }, + { std::uint8_t(opcode::OP_equality), "EQUALITY" }, + { std::uint8_t(opcode::OP_ClearLocalVariableFieldCached0), "CLEAR_LOCAL_VARIABLE_FIELD_CACHED_0" }, + { std::uint8_t(opcode::OP_notify), "NOTIFY" }, + { std::uint8_t(opcode::OP_GetVector), "GET_VECTOR" }, + { std::uint8_t(opcode::OP_ScriptMethodChildThreadCallPointer), "SCRIPT_METHOD_CHILD_THREAD_CALL_POINTER" }, + { std::uint8_t(opcode::OP_PreScriptCall), "PRE_SCRIPT_CALL" }, + { std::uint8_t(opcode::OP_GetByte), "GET_BYTE" }, + { std::uint8_t(opcode::OP_ScriptFarThreadCall), "SCRIPT_FAR_THREAD_CALL" }, + { std::uint8_t(opcode::OP_SetSelfFieldVariableField), "SET_SELF_FIELD_VARIABLE_FIELD" }, + { std::uint8_t(opcode::OP_JumpOnFalseExpr), "JUMP_ON_FALSE_EXPR" }, + { std::uint8_t(opcode::OP_GetUndefined), "GET_UNDEFINED" }, + { std::uint8_t(opcode::OP_jumpback), "JUMP_BACK" }, + { std::uint8_t(opcode::OP_JumpOnTrueExpr), "JUMP_ON_TRUE_EXPR" }, + { std::uint8_t(opcode::OP_CallBuiltin0),"CALL_BUILTIN_FUNC_0" }, + { std::uint8_t(opcode::OP_CallBuiltin1),"CALL_BUILTIN_FUNC_1" }, + { std::uint8_t(opcode::OP_CallBuiltin2),"CALL_BUILTIN_FUNC_2" }, + { std::uint8_t(opcode::OP_CallBuiltin3),"CALL_BUILTIN_FUNC_3" }, + { std::uint8_t(opcode::OP_CallBuiltin4),"CALL_BUILTIN_FUNC_4" }, + { std::uint8_t(opcode::OP_CallBuiltin5),"CALL_BUILTIN_FUNC_5" }, + { std::uint8_t(opcode::OP_CallBuiltin),"CALL_BUILTIN_FUNC" }, + { std::uint8_t(opcode::OP_SetLocalVariableFieldCached0), "SET_LOCAL_VARIABLE_FIELD_CACHED_0" }, + { std::uint8_t(opcode::OP_ClearFieldVariable), "CLEAR_FIELD_VARIABLE" }, + { std::uint8_t(opcode::OP_GetLevel), "GET_LEVEL" }, + { std::uint8_t(opcode::OP_size), "SIZE" }, + { std::uint8_t(opcode::OP_SafeSetWaittillVariableFieldCached), "SAFE_SET_WAITTILL_VARIABLE_FIELD_CACHED" }, + { std::uint8_t(opcode::OP_ScriptLocalMethodThreadCall), "SCRIPT_LOCAL_METHOD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_AddArray), "ADD_ARRAY" }, + { std::uint8_t(opcode::OP_endon), "ENDON" }, + { std::uint8_t(opcode::OP_EvalFieldVariable), "EVAL_FIELD_VARIABLE" }, + { std::uint8_t(opcode::OP_shift_left), "SHIFT_LEFT" }, + { std::uint8_t(opcode::OP_EvalLocalArrayRefCached0), "EVAL_LOCAL_ARRAY_REF_CACHED_0" }, + { std::uint8_t(opcode::OP_Return), "RETURN" }, + { std::uint8_t(opcode::OP_CreateLocalVariable), "CREATE_LOCAL_VARIABLE" }, + { std::uint8_t(opcode::OP_SafeSetVariableFieldCached0), "SAFE_SET_VARIABLE_FIELD_CACHED_0" }, + { std::uint8_t(opcode::OP_GetBuiltinFunction), "GET_BUILTIN_FUNCTION" }, + { std::uint8_t(opcode::OP_ScriptLocalMethodCall), "SCRIPT_LOCAL_METHOD_CALL" }, + { std::uint8_t(opcode::OP_CallBuiltinMethodPointer), "CALL_BUILTIN_METHOD_POINTER" }, + { std::uint8_t(opcode::OP_ScriptLocalChildThreadCall), "SCRIPT_LOCAL_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_GetSelfObject), "GET_SELF_OBJECT" }, + { std::uint8_t(opcode::OP_GetGame), "GET_GAME" }, + { std::uint8_t(opcode::OP_SetLevelFieldVariableField), "SET_LEVEL_FIELD_VARIABLE_FIELD" }, + { std::uint8_t(opcode::OP_EvalArray), "EVAL_ARRAY" }, + { std::uint8_t(opcode::OP_GetSelf), "GET_SELF" }, + { std::uint8_t(opcode::OP_End), "END" }, + { std::uint8_t(opcode::OP_EvalSelfFieldVariable), "EVAL_SELF_FIELD_VARIABLE" }, + { std::uint8_t(opcode::OP_less_equal), "LESS_EQUAL" }, + { std::uint8_t(opcode::OP_EvalLocalVariableCached0), "EVAL_LOCAL_VARIABLE_CACHED_0" }, + { std::uint8_t(opcode::OP_EvalLocalVariableCached1), "EVAL_LOCAL_VARIABLE_CACHED_1" }, + { std::uint8_t(opcode::OP_EvalLocalVariableCached2), "EVAL_LOCAL_VARIABLE_CACHED_2" }, + { std::uint8_t(opcode::OP_EvalLocalVariableCached3), "EVAL_LOCAL_VARIABLE_CACHED_3" }, + { std::uint8_t(opcode::OP_EvalLocalVariableCached4), "EVAL_LOCAL_VARIABLE_CACHED_4" }, + { std::uint8_t(opcode::OP_EvalLocalVariableCached5), "EVAL_LOCAL_VARIABLE_CACHED_5" }, + { std::uint8_t(opcode::OP_EvalLocalVariableCached), "EVAL_LOCAL_VARIABLE_CACHED" }, + { std::uint8_t(opcode::OP_EvalNewLocalArrayRefCached0), "EVAL_NEW_LOCAL_ARRAY_REF_CACHED_0" }, + { std::uint8_t(opcode::OP_ScriptChildThreadCallPointer), "SCRIPT_CHILD_THREAD_CALL_POINTER" }, + { std::uint8_t(opcode::OP_EvalLocalVariableObjectCached), "EVAL_LOCAL_VARIABLE_OBJECT_CACHED" }, + { std::uint8_t(opcode::OP_ScriptLocalThreadCall), "SCRIPT_LOCAL_THREAD_CALL" }, + { std::uint8_t(opcode::OP_GetInteger), "GET_INTEGER" }, + { std::uint8_t(opcode::OP_ScriptMethodCallPointer), "SCRIPT_METHOD_CALL_POINTER" }, + { std::uint8_t(opcode::OP_checkclearparams), "CHECK_CLEAR_PARAMS" }, + { std::uint8_t(opcode::OP_SetAnimFieldVariableField), "SET_ANIM_FIELD_VARIABLE_FIELD" }, + { std::uint8_t(opcode::OP_waittillmatch2), "WAITTILLMATCH2" }, + { std::uint8_t(opcode::OP_minus), "MINUS" }, + { std::uint8_t(opcode::OP_ScriptLocalFunctionCall2), "SCRIPT_LOCAL_FUNCTION_CALL2" }, + { std::uint8_t(opcode::OP_GetNegUnsignedShort), "GET_NEG_USHORT" }, + { std::uint8_t(opcode::OP_GetNegByte), "GET_NEG_BYTE" }, + { std::uint8_t(opcode::OP_SafeCreateVariableFieldCached), "SAFE_CREATE_VARIABLE_FIELD_CACHED" }, + { std::uint8_t(opcode::OP_greater_equal), "GREATER_EQUAL" }, + { std::uint8_t(opcode::OP_vector), "VECTOR" }, + { std::uint8_t(opcode::OP_GetBuiltinMethod), "GET_BUILTIN_METHOD" }, + { std::uint8_t(opcode::OP_endswitch), "END_SWITCH" }, + { std::uint8_t(opcode::OP_ClearArray), "CLEAR_ARRAY" }, + { std::uint8_t(opcode::OP_DecTop), "DECREMENT_TOP" }, + { std::uint8_t(opcode::OP_CastBool), "CAST_BOOL" }, + { std::uint8_t(opcode::OP_EvalArrayRef), "EVAL_ARRAY_REF" }, + { std::uint8_t(opcode::OP_SetNewLocalVariableFieldCached0), "SET_NEW_LOCAL_VARIABLE_FIELD_CACHED_0" }, + { std::uint8_t(opcode::OP_GetZero), "GET_ZERO" }, + { std::uint8_t(opcode::OP_wait), "WAIT" }, + { std::uint8_t(opcode::OP_waittill), "WAITTILL" }, + { std::uint8_t(opcode::OP_GetIString), "GET_ISTRING" }, + { std::uint8_t(opcode::OP_ScriptFarFunctionCall), "SCRIPT_FAR_FUNCTION_CALL" }, + { std::uint8_t(opcode::OP_GetAnimObject), "GET_ANIM_OBJECT" }, + { std::uint8_t(opcode::OP_GetAnimTree), "GET_ANIMTREE" }, + { std::uint8_t(opcode::OP_EvalLocalArrayCached), "EVAL_LOCAL_ARRAY_CACHED" }, + { std::uint8_t(opcode::OP_mod), "MOD" }, + { std::uint8_t(opcode::OP_ScriptFarMethodThreadCall), "SCRIPT_FAR_METHOD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_GetUnsignedShort), "GET_USHORT" }, + { std::uint8_t(opcode::OP_clearparams), "CLEAR_PARAMS" }, + { std::uint8_t(opcode::OP_ScriptMethodThreadCallPointer), "SCRIPT_METHOD_THREAD_CALL_POINTER" }, + { std::uint8_t(opcode::OP_ScriptFunctionCallPointer), "SCRIPT_FUNCTION_CALL_POINTER" }, + { std::uint8_t(opcode::OP_EmptyArray), "EMPTY_ARRAY" }, + { std::uint8_t(opcode::OP_SafeSetVariableFieldCached), "SAFE_SET_VARIABLE_FIELD_CACHED" }, + { std::uint8_t(opcode::OP_ClearVariableField), "CLEAR_VARIABLE_FIELD" }, + { std::uint8_t(opcode::OP_EvalFieldVariableRef), "EVAL_FIELD_VARIABLE_REF" }, + { std::uint8_t(opcode::OP_ScriptLocalMethodChildThreadCall), "SCRIPT_LOCAL_METHOD_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_EvalNewLocalVariableRefCached0), "EVAL_NEW_LOCAL_VARIABLE_REF_CACHED_0" }, + { std::uint8_t(opcode::OP_GetFloat), "GET_FLOAT" }, + { std::uint8_t(opcode::OP_EvalLocalVariableRefCached), "EVAL_LOCAL_VARIABLE_REF_CACHED" }, + { std::uint8_t(opcode::OP_JumpOnFalse), "JUMP_ON_FALSE" }, + { std::uint8_t(opcode::OP_BoolComplement), "BOOL_COMPLEMENT" }, + { std::uint8_t(opcode::OP_ScriptThreadCallPointer), "SCRIPT_THREAD_CALL_POINTER" }, + { std::uint8_t(opcode::OP_ScriptFarFunctionCall2), "SCRIPT_FAR_FUNCTION_CALL2" }, + { std::uint8_t(opcode::OP_less), "LESS" }, + { std::uint8_t(opcode::OP_BoolNot), "BOOL_NOT" }, + { std::uint8_t(opcode::OP_waittillFrameEnd), "WAITTILLFRAMEEND" }, + { std::uint8_t(opcode::OP_waitframe), "WAITFRAME" }, + { std::uint8_t(opcode::OP_GetString), "GET_STRING" }, + { std::uint8_t(opcode::OP_EvalLevelFieldVariable), "EVAL_LEVEL_FIELD_VARIABLE" }, + { std::uint8_t(opcode::OP_GetLevelObject), "GET_LEVEL_OBJECT" }, + { std::uint8_t(opcode::OP_inc), "INCREMENT" }, + { std::uint8_t(opcode::OP_CallBuiltinMethod0),"CALL_BUILTIN_METHOD_0" }, + { std::uint8_t(opcode::OP_CallBuiltinMethod1),"CALL_BUILTIN_METHOD_1" }, + { std::uint8_t(opcode::OP_CallBuiltinMethod2),"CALL_BUILTIN_METHOD_2" }, + { std::uint8_t(opcode::OP_CallBuiltinMethod3),"CALL_BUILTIN_METHOD_3" }, + { std::uint8_t(opcode::OP_CallBuiltinMethod4),"CALL_BUILTIN_METHOD_4" }, + { std::uint8_t(opcode::OP_CallBuiltinMethod5),"CALL_BUILTIN_METHOD_5" }, + { std::uint8_t(opcode::OP_CallBuiltinMethod),"CALL_BUILTIN_METHOD" }, + { std::uint8_t(opcode::OP_GetAnim), "GET_ANIM" }, + { std::uint8_t(opcode::OP_switch), "SWITCH" }, + { std::uint8_t(opcode::OP_SetVariableField), "SET_VARIABLE_FIELD" }, + { std::uint8_t(opcode::OP_divide), "DIV" }, + { std::uint8_t(opcode::OP_GetLocalFunction), "GET_LOCAL_FUNCTION" }, + { std::uint8_t(opcode::OP_ScriptFarChildThreadCall), "SCRIPT_FAR_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_multiply), "MUL" }, + { std::uint8_t(opcode::OP_ClearLocalVariableFieldCached), "CLEAR_LOCAL_VARIABLE_FIELD_CACHED" }, + { std::uint8_t(opcode::OP_EvalAnimFieldVariableRef), "EVAL_ANIM_FIELD_VARIABLE_REF" }, + { std::uint8_t(opcode::OP_EvalLocalArrayRefCached), "EVAL_LOCAL_ARRAY_REF_CACHED" }, + { std::uint8_t(opcode::OP_EvalLocalVariableRefCached0), "EVAL_LOCAL_VARIABLE_REF_CACHED_0" }, + { std::uint8_t(opcode::OP_bit_and), "BIT_AND" }, + { std::uint8_t(opcode::OP_GetAnimation), "GET_ANIMATION" }, + { std::uint8_t(opcode::OP_GetFarFunction), "GET_FAR_FUNCTION" }, + { std::uint8_t(opcode::OP_CallBuiltinPointer), "CALL_BUILTIN_POINTER" }, + { std::uint8_t(opcode::OP_jump), "JUMP" }, + { std::uint8_t(opcode::OP_voidCodepos), "VOIDCODEPOS" }, + { std::uint8_t(opcode::OP_ScriptFarMethodCall), "SCRIPT_FAR_METHOD_CALL" }, + { std::uint8_t(opcode::OP_inequality), "INEQUALITY" }, + { std::uint8_t(opcode::OP_ScriptLocalFunctionCall), "SCRIPT_LOCAL_FUNCTION_CALL" }, + { std::uint8_t(opcode::OP_bit_ex_or), "BIT_EXOR" }, + { std::uint8_t(opcode::OP_NOP), "NOP" }, + { std::uint8_t(opcode::OP_abort), "ABORT" }, + { std::uint8_t(opcode::OP_object), "OBJECT" }, + { std::uint8_t(opcode::OP_thread_object), "THREAD_OBJECT" }, + { std::uint8_t(opcode::OP_EvalLocalVariable), "EVAL_LOCAL_VARIABLE" }, + { std::uint8_t(opcode::OP_EvalLocalVariableRef), "EVAL_LOCAL_VARIABLE_REF" }, + { std::uint8_t(opcode::OP_prof_begin), "PROF_BEGIN" }, + { std::uint8_t(opcode::OP_prof_end), "PROF_END" }, + { std::uint8_t(opcode::OP_breakpoint), "BREAKPOINT" }, + { std::uint8_t(opcode::OP_assignmentBreakpoint), "ASSIGN_BREAKPOINT" }, + { std::uint8_t(opcode::OP_manualAndAssignmentBreakpoint), "MANUAL_AND_ASSIGN_BREAKPOINT" }, + { std::uint8_t(opcode::OP_BoolNotAfterAnd), "BOOL_NOT_AFTER_AND" }, + { std::uint8_t(opcode::OP_FormalParams), "FORMAL_PARAMS" }, + { std::uint8_t(opcode::OP_IsDefined), "IS_DEFINED" }, + { std::uint8_t(opcode::OP_IsTrue), "IS_TRUE" }, + { std::uint8_t(opcode::OP_NativeGetLocalFunction), "NATIVE_GET_LOCAL_FUNCTION" }, + { std::uint8_t(opcode::OP_NativeLocalFunctionCall), "NATIVE_LOCAL_FUNCTION_CALL" }, + { std::uint8_t(opcode::OP_NativeLocalFunctionCall2), "NATIVE_LOCAL_FUNCTION_CALL2" }, + { std::uint8_t(opcode::OP_NativeLocalMethodCall), "NATIVE_LOCAL_METHOD_CALL" }, + { std::uint8_t(opcode::OP_NativeLocalFunctionThreadCall), "NATIVE_LOCAL_FUNCTION_THREAD_CALL" }, + { std::uint8_t(opcode::OP_NativeLocalMethodThreadCall), "NATIVE_LOCAL_METHOD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_NativeLocalFunctionChildThreadCall), "NATIVE_LOCAL_FUNCTION_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_NativeLocalMethodChildThreadCall), "NATIVE_LOCAL_METHOD_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_NativeGetFarFunction), "NATIVE_GET_FAR_FUNCTION" }, + { std::uint8_t(opcode::OP_NativeFarFunctionCall), "NATIVE_FAR_FUNCTION_CALL" }, + { std::uint8_t(opcode::OP_NativeFarFunctionCall2), "NATIVE_FAR_FUNCTION_CALL2" }, + { std::uint8_t(opcode::OP_NativeFarMethodCall), "NATIVE_FAR_METHOD_CALL" }, + { std::uint8_t(opcode::OP_NativeFarFunctionThreadCall), "NATIVE_FAR_FUNCTION_THREAD_CALL" }, + { std::uint8_t(opcode::OP_NativeFarMethodThreadCall), "NATIVE_FAR_METHOD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_NativeFarFunctionChildThreadCall), "NATIVE_FAR_FUNCTION_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_NativeFarMethodChildThreadCall), "NATIVE_FAR_METHOD_CHILD_THREAD_CALL" }, + { std::uint8_t(opcode::OP_EvalNewLocalArrayRefCached0_Precompiled), "EVAL_NEW_LOCAL_ARRAY_REF_CACHED_0_PRECOMPILED" }, + { std::uint8_t(opcode::OP_SetNewLocalVariableFieldCached0_Precompiled), "SET_NEW_LOCAL_VARIABLE_FIELD_CACHED_0_PRECOMPILED" }, + { std::uint8_t(opcode::OP_CreateLocalVariable_Precompiled), "CREATE_LOCAL_VARIABLE_PRECOMPILED" }, + { std::uint8_t(opcode::OP_SafeCreateVariableFieldCached_Precompiled), "SAFE_CREATE_VARIABLE_FIELD_CACHED_PRECOMPILED" }, + { std::uint8_t(opcode::OP_FormalParams_Precompiled), "FORMAL_PARAMS_PRECOMPILED" }, +}}; + +const std::array function_list +{{ + { 0x08F, "getdvar" }, + { 0x09B, "getfirstarraykey" }, + { 0x0B1, "getnextarraykey" }, + { 0x126, "isusingmatchrulesdata" }, +}}; +const std::array method_list +{{ + { 0x0, "null" }, +}}; + +const std::array file_list +{{ + { 0x0, "null" }, +}}; + +const std::array token_list +{{ + { 0x00, "" }, // VOID + { 0x01, "pl#" }, // PL + { 0x02, "-" }, // MINUS +// { 0x03, "" }, // RADIUS_TYPO + { 0x04, ":" }, // NOTE_COLON +}}; + +struct __init__ +{ + __init__() + { + static bool init = false; + if(init) return; + init = true; + + opcode_map.reserve(opcode_list.size()); + opcode_map_rev.reserve(opcode_list.size()); + function_map.reserve(function_list.size()); + function_map_rev.reserve(function_list.size()); + method_map.reserve(method_list.size()); + method_map_rev.reserve(method_list.size()); + file_map.reserve(file_list.size()); + file_map_rev.reserve(file_list.size()); + token_map.reserve(token_list.size()); + token_map_rev.reserve(token_list.size()); + + for(const auto& entry : opcode_list) + { + opcode_map.insert({ entry.key, entry.value }); + opcode_map_rev.insert({ entry.value, entry.key }); + } + + for(const auto& entry : function_list) + { + function_map.insert({ entry.key, entry.value }); + function_map_rev.insert({ entry.value, entry.key }); + } + + for(const auto& entry : method_list) + { + method_map.insert({ entry.key, entry.value }); + method_map_rev.insert({ entry.value, entry.key }); + } + + for(const auto& entry : file_list) + { + file_map.insert({ entry.key, entry.value }); + file_map_rev.insert({ entry.value, entry.key }); + } + + for(const auto& entry : token_list) + { + token_map.insert({ entry.key, entry.value }); + token_map_rev.insert({ entry.value, entry.key }); + } + } +}; + +__init__ _; + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/resolver.hpp b/src/s4/xsk/resolver.hpp new file mode 100644 index 00000000..1f53985f --- /dev/null +++ b/src/s4/xsk/resolver.hpp @@ -0,0 +1,33 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#pragma once + +namespace xsk::gsc::s4 +{ + +class resolver +{ +public: + static auto opcode_id(const std::string& name) -> std::uint8_t; + static auto opcode_name(std::uint8_t id) -> std::string; + + static auto function_id(const std::string& name) -> std::uint16_t; + static auto function_name(std::uint16_t id) -> std::string; + + static auto method_id(const std::string& name) -> std::uint16_t; + static auto method_name(std::uint16_t id) -> std::string; + + static auto file_id(const std::string& name) -> std::uint32_t; + static auto file_name(std::uint32_t id) -> std::string; + + static auto token_id(const std::string& name) -> std::uint32_t; + static auto token_name(std::uint32_t id) -> std::string; + + static auto find_function(const std::string& name) -> bool; + static auto find_method(const std::string& name) -> bool; +}; + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/s4.cpp b/src/s4/xsk/s4.cpp new file mode 100644 index 00000000..1467137d --- /dev/null +++ b/src/s4/xsk/s4.cpp @@ -0,0 +1,229 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#include "stdafx.hpp" +#include "s4.hpp" + +namespace xsk::gsc::s4 +{ + +auto opcode_size(std::uint8_t id) -> std::uint32_t +{ + switch (opcode(id)) + { + case opcode::OP_CastFieldObject: + case opcode::OP_plus: + case opcode::OP_GetGameRef: + case opcode::OP_GetThisthread: + case opcode::OP_greater: + case opcode::OP_shift_right: + case opcode::OP_dec: + case opcode::OP_bit_or: + case opcode::OP_equality: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_notify: + case opcode::OP_PreScriptCall: + case opcode::OP_GetUndefined: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_GetLevel: + case opcode::OP_size: + case opcode::OP_AddArray: + case opcode::OP_endon: + case opcode::OP_shift_left: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_Return: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_GetSelfObject: + case opcode::OP_GetGame: + case opcode::OP_EvalArray: + case opcode::OP_GetSelf: + case opcode::OP_End: + case opcode::OP_less_equal: + case opcode::OP_EvalLocalVariableCached0: + case opcode::OP_EvalLocalVariableCached1: + case opcode::OP_EvalLocalVariableCached2: + case opcode::OP_EvalLocalVariableCached3: + case opcode::OP_EvalLocalVariableCached4: + case opcode::OP_EvalLocalVariableCached5: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_checkclearparams: + case opcode::OP_waittillmatch2: + case opcode::OP_minus: + case opcode::OP_greater_equal: + case opcode::OP_vector: + case opcode::OP_ClearArray: + case opcode::OP_DecTop: + case opcode::OP_CastBool: + case opcode::OP_EvalArrayRef: + case opcode::OP_GetZero: + case opcode::OP_wait: + case opcode::OP_waittill: + case opcode::OP_GetAnimObject: + case opcode::OP_mod: + case opcode::OP_clearparams: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_EmptyArray: + case opcode::OP_ClearVariableField: + case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_BoolComplement: + case opcode::OP_less: + case opcode::OP_BoolNot: + case opcode::OP_waittillFrameEnd: + case opcode::OP_waitframe: + case opcode::OP_GetLevelObject: + case opcode::OP_inc: + case opcode::OP_GetAnim: + case opcode::OP_SetVariableField: + case opcode::OP_divide: + case opcode::OP_multiply: + case opcode::OP_EvalLocalVariableRefCached0: + case opcode::OP_bit_and: + case opcode::OP_voidCodepos: + case opcode::OP_inequality: + case opcode::OP_bit_ex_or: +/* + case opcode::OP_NOP: + case opcode::OP_abort: + case opcode::OP_object: + case opcode::OP_thread_object: + case opcode::OP_EvalLocalVariable: + case opcode::OP_EvalLocalVariableRef: + case opcode::OP_breakpoint: + case opcode::OP_assignmentBreakpoint: + case opcode::OP_manualAndAssignmentBreakpoint: +*/ + case opcode::OP_BoolNotAfterAnd: + case opcode::OP_IsDefined: + case opcode::OP_IsTrue: + return 1; + case opcode::OP_SetLocalVariableFieldCached: + case opcode::OP_RemoveLocalVariables: + case opcode::OP_ScriptMethodChildThreadCallPointer: + case opcode::OP_GetByte: + case opcode::OP_SafeSetWaittillVariableFieldCached: + case opcode::OP_CreateLocalVariable: + case opcode::OP_CallBuiltinMethodPointer: + case opcode::OP_EvalLocalVariableCached: + case opcode::OP_EvalNewLocalArrayRefCached0: + case opcode::OP_ScriptChildThreadCallPointer: + case opcode::OP_EvalLocalVariableObjectCached: + case opcode::OP_GetNegByte: + case opcode::OP_SafeCreateVariableFieldCached: + case opcode::OP_SetNewLocalVariableFieldCached0: + case opcode::OP_GetAnimTree: + case opcode::OP_EvalLocalArrayCached: + case opcode::OP_ScriptMethodThreadCallPointer: + case opcode::OP_SafeSetVariableFieldCached: + case opcode::OP_EvalLocalVariableRefCached: + case opcode::OP_ScriptThreadCallPointer: + case opcode::OP_ClearLocalVariableFieldCached: + case opcode::OP_EvalLocalArrayRefCached: + case opcode::OP_CallBuiltinPointer: +// case opcode::OP_prof_end: + case opcode::OP_FormalParams: +/* + case opcode::OP_EvalNewLocalArrayRefCached0_Precompiled: + case opcode::OP_SetNewLocalVariableFieldCached0_Precompiled: + case opcode::OP_CreateLocalVariable_Precompiled: + case opcode::OP_SafeCreateVariableFieldCached_Precompiled: + case opcode::OP_FormalParams_Precompiled: +*/ + return 2; + case opcode::OP_waittillmatch: + case opcode::OP_JumpOnTrue: + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_jumpback: + case opcode::OP_JumpOnTrueExpr: + case opcode::OP_CallBuiltin0: + case opcode::OP_CallBuiltin1: + case opcode::OP_CallBuiltin2: + case opcode::OP_CallBuiltin3: + case opcode::OP_CallBuiltin4: + case opcode::OP_CallBuiltin5: + case opcode::OP_GetBuiltinFunction: + case opcode::OP_GetNegUnsignedShort: + case opcode::OP_GetBuiltinMethod: + case opcode::OP_endswitch: + case opcode::OP_GetUnsignedShort: + case opcode::OP_JumpOnFalse: + case opcode::OP_CallBuiltinMethod0: + case opcode::OP_CallBuiltinMethod1: + case opcode::OP_CallBuiltinMethod2: + case opcode::OP_CallBuiltinMethod3: + case opcode::OP_CallBuiltinMethod4: + case opcode::OP_CallBuiltinMethod5: + return 3; + case opcode::OP_CallBuiltin: + case opcode::OP_ScriptLocalMethodCall: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_CallBuiltinMethod: + case opcode::OP_GetLocalFunction: + case opcode::OP_GetFarFunction: + case opcode::OP_ScriptFarMethodCall: + case opcode::OP_ScriptLocalFunctionCall: +/* + case opcode::OP_NativeGetLocalFunction: + case opcode::OP_NativeLocalFunctionCall: + case opcode::OP_NativeLocalFunctionCall2: + case opcode::OP_NativeLocalMethodCall: + case opcode::OP_NativeGetFarFunction: + case opcode::OP_NativeFarFunctionCall: + case opcode::OP_NativeFarFunctionCall2: + case opcode::OP_NativeFarMethodCall: +*/ + return 4; + case opcode::OP_EvalSelfFieldVariableRef: + case opcode::OP_ScriptFarMethodChildThreadCall: + case opcode::OP_EvalAnimFieldVariable: + case opcode::OP_EvalLevelFieldVariableRef: + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_SetSelfFieldVariableField: + case opcode::OP_ClearFieldVariable: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_EvalFieldVariable: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_SetLevelFieldVariableField: + case opcode::OP_EvalSelfFieldVariable: + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_GetInteger: + case opcode::OP_SetAnimFieldVariableField: + case opcode::OP_GetIString: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_EvalFieldVariableRef: + case opcode::OP_ScriptLocalMethodChildThreadCall: + case opcode::OP_GetFloat: + case opcode::OP_GetString: + case opcode::OP_EvalLevelFieldVariable: + case opcode::OP_switch: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_EvalAnimFieldVariableRef: + case opcode::OP_jump: +/* + case opcode::OP_NativeLocalFunctionThreadCall: + case opcode::OP_NativeLocalMethodThreadCall: + case opcode::OP_NativeLocalFunctionChildThreadCall: + case opcode::OP_NativeLocalMethodChildThreadCall: + case opcode::OP_NativeFarFunctionThreadCall: + case opcode::OP_NativeFarMethodThreadCall: + case opcode::OP_NativeFarFunctionChildThreadCall: + case opcode::OP_NativeFarMethodChildThreadCall: +*/ + return 5; +/* + case opcode::OP_prof_begin: + return 6; +*/ + case opcode::OP_GetAnimation: + return 9; + case opcode::OP_GetVector: + return 13; + default: + throw std::runtime_error("Couldn't resolve instruction size for " + std::to_string(id)); + } +} + +} // namespace xsk::gsc::s4 diff --git a/src/s4/xsk/s4.hpp b/src/s4/xsk/s4.hpp new file mode 100644 index 00000000..f4e96ce1 --- /dev/null +++ b/src/s4/xsk/s4.hpp @@ -0,0 +1,216 @@ +// Copyright 2021 xensik. All rights reserved. +// +// Use of this source code is governed by a GNU GPLv3 license +// that can be found in the LICENSE file. + +#pragma once + +#include "utils/xsk/utils.hpp" + +#include "assembler.hpp" +#include "disassembler.hpp" +#include "compiler.hpp" +#include "decompiler.hpp" +#include "resolver.hpp" + +namespace xsk::gsc::s4 +{ + +enum class opcode : std::uint8_t +{ + OP_CastFieldObject = 0x0, + OP_SetLocalVariableFieldCached = 0x1, + OP_plus = 0x2, + OP_RemoveLocalVariables = 0x3, + OP_EvalSelfFieldVariableRef = 0x4, + OP_ScriptFarMethodChildThreadCall = 0x5, + OP_GetGameRef = 0x6, + OP_EvalAnimFieldVariable = 0x7, + OP_EvalLevelFieldVariableRef = 0x8, + OP_GetThisthread = 0x9, + OP_greater = 0xA, + OP_waittillmatch = 0xB, + OP_shift_right = 0xC, + OP_dec = 0xD, + OP_JumpOnTrue = 0xE, + OP_bit_or = 0xF, + OP_equality = 0x10, + OP_ClearLocalVariableFieldCached0 = 0x11, + OP_notify = 0x12, + OP_GetVector = 0x13, + OP_ScriptMethodChildThreadCallPointer = 0x14, + OP_PreScriptCall = 0x15, + OP_GetByte = 0x16, + OP_ScriptFarThreadCall = 0x17, + OP_SetSelfFieldVariableField = 0x18, + OP_JumpOnFalseExpr = 0x19, + OP_GetUndefined = 0x1A, + OP_jumpback = 0x1B, + OP_JumpOnTrueExpr = 0x1C, + OP_CallBuiltin0 = 0x1D, + OP_CallBuiltin1 = 0x1E, + OP_CallBuiltin2 = 0x1F, + OP_CallBuiltin3 = 0x20, + OP_CallBuiltin4 = 0x21, + OP_CallBuiltin5 = 0x22, + OP_CallBuiltin = 0x23, + OP_SetLocalVariableFieldCached0 = 0x24, + OP_ClearFieldVariable = 0x25, + OP_GetLevel = 0x26, + OP_size = 0x27, + OP_SafeSetWaittillVariableFieldCached = 0x28, + OP_ScriptLocalMethodThreadCall = 0x29, + OP_AddArray = 0x2A, + OP_endon = 0x2B, + OP_EvalFieldVariable = 0x2C, + OP_shift_left = 0x2D, + OP_EvalLocalArrayRefCached0 = 0x2E, + OP_Return = 0x2F, + OP_CreateLocalVariable = 0x30, + OP_SafeSetVariableFieldCached0 = 0x31, + OP_GetBuiltinFunction = 0x32, + OP_ScriptLocalMethodCall = 0x33, + OP_CallBuiltinMethodPointer = 0x34, + OP_ScriptLocalChildThreadCall = 0x35, + OP_GetSelfObject = 0x36, + OP_GetGame = 0x37, + OP_SetLevelFieldVariableField = 0x38, + OP_EvalArray = 0x39, + OP_GetSelf = 0x3A, + OP_End = 0x3B, + OP_EvalSelfFieldVariable = 0x3C, + OP_less_equal = 0x3D, + OP_EvalLocalVariableCached0 = 0x3E, + OP_EvalLocalVariableCached1 = 0x3F, + OP_EvalLocalVariableCached2 = 0x40, + OP_EvalLocalVariableCached3 = 0x41, + OP_EvalLocalVariableCached4 = 0x42, + OP_EvalLocalVariableCached5 = 0x43, + OP_EvalLocalVariableCached = 0x44, + OP_EvalNewLocalArrayRefCached0 = 0x45, + OP_ScriptChildThreadCallPointer = 0x46, + OP_EvalLocalVariableObjectCached = 0x47, + OP_ScriptLocalThreadCall = 0x48, + OP_GetInteger = 0x49, + OP_ScriptMethodCallPointer = 0x4A, + OP_checkclearparams = 0x4B, + OP_SetAnimFieldVariableField = 0x4C, + OP_waittillmatch2 = 0x4D, + OP_minus = 0x4E, + OP_ScriptLocalFunctionCall2 = 0x4F, + OP_GetNegUnsignedShort = 0x50, + OP_GetNegByte = 0x51, + OP_SafeCreateVariableFieldCached = 0x52, + OP_greater_equal = 0x53, + OP_vector = 0x54, + OP_GetBuiltinMethod = 0x55, + OP_endswitch = 0x56, + OP_ClearArray = 0x57, + OP_DecTop = 0x58, + OP_CastBool = 0x59, + OP_EvalArrayRef = 0x5A, + OP_SetNewLocalVariableFieldCached0 = 0x5B, + OP_GetZero = 0x5C, + OP_wait = 0x5D, + OP_waittill = 0x5E, + OP_GetIString = 0x5F, + OP_ScriptFarFunctionCall = 0x60, + OP_GetAnimObject = 0x61, + OP_GetAnimTree = 0x62, + OP_EvalLocalArrayCached = 0x63, + OP_mod = 0x64, + OP_ScriptFarMethodThreadCall = 0x65, + OP_GetUnsignedShort = 0x66, + OP_clearparams = 0x67, + OP_ScriptMethodThreadCallPointer = 0x68, + OP_ScriptFunctionCallPointer = 0x69, + OP_EmptyArray = 0x6A, + OP_SafeSetVariableFieldCached = 0x6B, + OP_ClearVariableField = 0x6C, + OP_EvalFieldVariableRef = 0x6D, + OP_ScriptLocalMethodChildThreadCall = 0x6E, + OP_EvalNewLocalVariableRefCached0 = 0x6F, + OP_GetFloat = 0x70, + OP_EvalLocalVariableRefCached = 0x71, + OP_JumpOnFalse = 0x72, + OP_BoolComplement = 0x73, + OP_ScriptThreadCallPointer = 0x74, + OP_ScriptFarFunctionCall2 = 0x75, + OP_less = 0x76, + OP_BoolNot = 0x77, + OP_waittillFrameEnd = 0x78, + OP_waitframe = 0x79, + OP_GetString = 0x7A, + OP_EvalLevelFieldVariable = 0x7B, + OP_GetLevelObject = 0x7C, + OP_inc = 0x7D, + OP_CallBuiltinMethod0 = 0x7E, + OP_CallBuiltinMethod1 = 0x7F, + OP_CallBuiltinMethod2 = 0x80, + OP_CallBuiltinMethod3 = 0x81, + OP_CallBuiltinMethod4 = 0x82, + OP_CallBuiltinMethod5 = 0x83, + OP_CallBuiltinMethod = 0x84, + OP_GetAnim = 0x85, + OP_switch = 0x86, + OP_SetVariableField = 0x87, + OP_divide = 0x88, + OP_GetLocalFunction = 0x89, + OP_ScriptFarChildThreadCall = 0x8A, + OP_multiply = 0x8B, + OP_ClearLocalVariableFieldCached = 0x8C, + OP_EvalAnimFieldVariableRef = 0x8D, + OP_EvalLocalArrayRefCached = 0x8E, + OP_EvalLocalVariableRefCached0 = 0x8F, + OP_bit_and = 0x90, + OP_GetAnimation = 0x91, + OP_GetFarFunction = 0x92, + OP_CallBuiltinPointer = 0x93, + OP_jump = 0x94, + OP_voidCodepos = 0x95, + OP_ScriptFarMethodCall = 0x96, + OP_inequality = 0x97, + OP_ScriptLocalFunctionCall = 0x98, + OP_bit_ex_or = 0x99, + OP_NOP = 0x9A, + OP_abort = 0x9B, + OP_object = 0x9C, + OP_thread_object = 0x9D, + OP_EvalLocalVariable = 0x9E, + OP_EvalLocalVariableRef = 0x9F, + OP_prof_begin = 0xA0, + OP_prof_end = 0xA1, + OP_breakpoint = 0xA2, + OP_assignmentBreakpoint = 0xA3, + OP_manualAndAssignmentBreakpoint = 0xA4, + OP_BoolNotAfterAnd = 0xA5, + OP_FormalParams = 0xA6, + OP_IsDefined = 0xA7, + OP_IsTrue = 0xA8, + OP_NativeGetLocalFunction = 0xA9, + OP_NativeLocalFunctionCall = 0xAA, + OP_NativeLocalFunctionCall2 = 0xAB, + OP_NativeLocalMethodCall = 0xAC, + OP_NativeLocalFunctionThreadCall = 0xAD, + OP_NativeLocalMethodThreadCall = 0xAE, + OP_NativeLocalFunctionChildThreadCall = 0xAF, + OP_NativeLocalMethodChildThreadCall = 0xB0, + OP_NativeGetFarFunction = 0xB1, + OP_NativeFarFunctionCall = 0xB2, + OP_NativeFarFunctionCall2 = 0xB3, + OP_NativeFarMethodCall = 0xB4, + OP_NativeFarFunctionThreadCall = 0xB5, + OP_NativeFarMethodThreadCall = 0xB6, + OP_NativeFarFunctionChildThreadCall = 0xB7, + OP_NativeFarMethodChildThreadCall = 0xB8, + OP_EvalNewLocalArrayRefCached0_Precompiled = 0xB9, + OP_SetNewLocalVariableFieldCached0_Precompiled = 0xBA, + OP_CreateLocalVariable_Precompiled = 0xBB, + OP_SafeCreateVariableFieldCached_Precompiled = 0xBC, + OP_FormalParams_Precompiled = 0xBD, + OP_count = 0xBE, +}; + +auto opcode_size(std::uint8_t op) -> std::uint32_t; + +} // namespace xsk::gsc::s4 diff --git a/src/tool/xsk/main.cpp b/src/tool/xsk/main.cpp index 58f32655..1287c975 100644 --- a/src/tool/xsk/main.cpp +++ b/src/tool/xsk/main.cpp @@ -11,6 +11,7 @@ #include "iw8/xsk/iw8.hpp" #include "s1/xsk/s1.hpp" #include "s2/xsk/s2.hpp" +#include "s4/xsk/s4.hpp" #include "h1/xsk/h1.hpp" #include "h2/xsk/h2.hpp" @@ -18,7 +19,7 @@ namespace xsk::gsc { enum class mode { __, ASM, DISASM, COMP, DECOMP }; -enum class game { __, IW5, IW6, IW7, IW8, S1, S2, H1, H2 }; +enum class game { __, IW5, IW6, IW7, IW8, S1, S2, S4, H1, H2 }; std::map modes = { @@ -36,6 +37,7 @@ std::map games = { "-iw8", game::IW8 }, { "-s1", game::S1 }, { "-s2", game::S2 }, + { "-s4", game::S4 }, { "-h1", game::H1 }, { "-h2", game::H2 }, }; @@ -76,6 +78,7 @@ auto choose_resolver_file_name(uint32_t id, game& game) -> std::string case game::IW8: return iw8::resolver::file_name(id); case game::S1: return s1::resolver::file_name(static_cast(id)); case game::S2: return s2::resolver::file_name(static_cast(id)); + case game::S4: return s4::resolver::file_name(id); case game::H1: return h1::resolver::file_name(static_cast(id)); case game::H2: return h2::resolver::file_name(static_cast(id)); default: return ""; @@ -386,7 +389,7 @@ int parse_flags(int argc, char** argv, game& game, mode& mode, bool& zonetool) void print_usage() { std::cout << "usage: gsc-tool.exe \n"; - std::cout << " * games: -iw5, -iw6, -iw7, -s1, -s2, -h1, -h2\n"; + std::cout << " * games: -iw5, -iw6, -iw7, -iw8, -s1, -s2, -s4, -h1, -h2\n"; std::cout << " * modes: -asm, -disasm, -comp, -decomp\n"; } @@ -435,6 +438,11 @@ std::uint32_t main(std::uint32_t argc, char** argv) s2::assembler assembler; assemble_file(assembler, file, zonetool); } + else if (game == game::S4) + { + s4::assembler assembler; + assemble_file(assembler, file, zonetool); + } else if (game == game::H1) { h1::assembler assembler; @@ -478,6 +486,11 @@ std::uint32_t main(std::uint32_t argc, char** argv) s2::disassembler disassembler; disassemble_file(disassembler, file, game, zonetool); } + else if (game == game::S4) + { + s4::disassembler disassembler; + disassemble_file(disassembler, file, game, zonetool); + } else if (game == game::H1) { h1::disassembler disassembler; @@ -527,6 +540,12 @@ std::uint32_t main(std::uint32_t argc, char** argv) s2::compiler compiler; compile_file(assembler, compiler, file ,zonetool); } + else if (game == game::S4) + { + s4::assembler assembler; + s4::compiler compiler; + compile_file(assembler, compiler, file ,zonetool); + } else if (game == game::H1) { h1::assembler assembler; @@ -578,6 +597,12 @@ std::uint32_t main(std::uint32_t argc, char** argv) s2::decompiler decompiler; decompile_file(disassembler, decompiler, file, game, zonetool); } + else if (game == game::S4) + { + s4::disassembler disassembler; + s4::decompiler decompiler; + decompile_file(disassembler, decompiler, file, game, zonetool); + } else if (game == game::H1) { h1::disassembler disassembler;