diff --git a/gen/experimental/iw6c/Makefile b/gen/experimental/iw6c/Makefile new file mode 100644 index 00000000..2f177794 --- /dev/null +++ b/gen/experimental/iw6c/Makefile @@ -0,0 +1,9 @@ +generate: iw6c + +clean: + rm -rf ./parser.hpp + rm -rf ./parser.cpp + +iw6c: parser.ypp + bison parser.ypp -Wcounterexamples + mv parser.hpp parser.cpp ../../../src/experimental/iw6c/xsk/ diff --git a/gen/experimental/iw6c/parser.ypp b/gen/experimental/iw6c/parser.ypp new file mode 100644 index 00000000..750c498c --- /dev/null +++ b/gen/experimental/iw6c/parser.ypp @@ -0,0 +1,888 @@ +/* Copyright 2022 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 {IW6C} +%define api.namespace {xsk::gsc::iw6c} +%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 { xsk::gsc::iw6c::lexer& lexer } +%parse-param { xsk::gsc::iw6c::lexer& lexer } +%parse-param { xsk::gsc::ast::program::ptr& ast } + +%code requires +{ +#ifdef _MSC_VER +#pragma warning(disable:4065) +#pragma warning(disable:4127) +#endif +#include "iw6c.hpp" +namespace xsk::gsc::iw6c { class lexer; } +} + +%code top +{ +#include "stdafx.hpp" +#include "parser.hpp" +#include "lexer.hpp" +using namespace xsk::gsc; +xsk::gsc::iw6c::parser::symbol_type IW6Clex(xsk::gsc::iw6c::lexer& lexer); +} + +%token SH_DEFINE "#define" +%token SH_UNDEF "#undef" +%token SH_IFDEF "#ifdef" +%token SH_IFNDEF "#ifndef" +%token SH_IF "#if" +%token SH_ELIF "#elif" +%token SH_ELSE "#else" +%token SH_ENDIF "#endif" +%token DEVBEGIN "/#" +%token DEVEND "#/" +%token INLINE "#inline" +%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 IF "if" +%token ELSE "else" +%token DO "do" +%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 BREAKPOINT "breakpoint" +%token PROFBEGIN "prof_begin" +%token PROFEND "prof_end" +%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_MUL "*=" +%token ASSIGN_DIV "/=" +%token ASSIGN_MOD "%=" +%token ASSIGN_BW_OR "|=" +%token ASSIGN_BW_AND "&=" +%token ASSIGN_BW_EXOR "^=" +%token ASSIGN_RSHIFT ">>=" +%token ASSIGN_LSHIFT "<<=" +%token BITWISE_OR "|" +%token BITWISE_AND "&" +%token BITWISE_EXOR "^" +%token ADD "+" +%token SUB "-" +%token MUL "*" +%token DIV "/" +%token MOD "%" +%token PATH "path" +%token IDENTIFIER "identifier" +%token STRING "string literal" +%token ISTRING "localized string" +%token FLOAT "float" +%token INTEGER "integer" + +%type program +%type include +%type declaration +%type decl_usingtree +%type decl_constant +%type decl_thread +%type stmt +%type stmt_or_dev +%type stmt_list +%type stmt_or_dev_list +%type stmt_dev +%type stmt_block +%type stmt_expr +%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_if +%type stmt_ifelse +%type stmt_while +%type stmt_dowhile +%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 stmt_breakpoint +%type stmt_prof_begin +%type stmt_prof_end +%type expr +%type expr_or_empty +%type expr_assign +%type expr_increment +%type expr_decrement +%type expr_ternary +%type expr_binary +%type expr_primitive +%type expr_complement +%type expr_negate +%type expr_not +%type expr_call +%type expr_method +%type expr_function +%type expr_pointer +%type expr_add_array +%type expr_parameters +%type expr_arguments +%type expr_arguments_no_empty +%type expr_reference +%type expr_tuple +%type expr_tuple_arguments +%type expr_tuple_types +%type expr_array +%type expr_field +%type expr_size +%type expr_paren +%type expr_object +%type expr_thisthread +%type expr_empty_array +%type expr_undefined +%type expr_game +%type expr_self +%type expr_anim +%type expr_level +%type expr_animation +%type expr_animtree +%type expr_identifier_nosize +%type expr_identifier +%type expr_path +%type expr_istring +%type expr_string +%type expr_vector +%type expr_float +%type expr_integer +%type expr_false +%type expr_true + +%nonassoc SIZEOF +%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_EXOR +%left BITWISE_AND +%left EQUALITY INEQUALITY +%left LESS GREATER LESS_EQUAL GREATER_EQUAL +%left LSHIFT RSHIFT +%left ADD SUB +%left MUL 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 inline + { $$ = std::move($1); } + | program include + { $$ = std::move($1); $$->includes.push_back(std::move($2)); } + | program declaration + { $$ = std::move($1); $$->declarations.push_back(std::move($2)); } + | inline + { $$ = std::make_unique(@$); } + | include + { $$ = std::make_unique(@$); $$->includes.push_back(std::move($1)); } + | declaration + { $$ = std::make_unique(@$); $$->declarations.push_back(std::move($1)); } + ; + +inline + : INLINE expr_path SEMICOLON { lexer.push_header($2->value); } + ; + +include + : INCLUDE expr_path SEMICOLON + { $$ = std::make_unique(@$, std::move($2)); } + ; + +declaration + : DEVBEGIN { $$.as_dev_begin = std::make_unique(@$); } + | DEVEND { $$.as_dev_end = std::make_unique(@$); } + | decl_usingtree { $$.as_usingtree = std::move($1); } + | decl_constant { $$.as_constant = std::move($1); } + | decl_thread { $$.as_thread = std::move($1); } + ; + +decl_usingtree + : USINGTREE LPAREN expr_string RPAREN SEMICOLON + { lexer.ban_header(@$); $$ = std::make_unique(@$, std::move($3)); } + ; + +decl_constant + : expr_identifier ASSIGN expr SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +decl_thread + : expr_identifier LPAREN expr_parameters RPAREN stmt_block + { lexer.ban_header(@$); $$ = std::make_unique(@$, std::move($1), std::move($3), std::move($5)); } + ; + +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_if { $$.as_if = std::move($1); } + | stmt_ifelse { $$.as_ifelse = std::move($1); } + | stmt_while { $$.as_while = std::move($1); } + | stmt_dowhile { $$.as_dowhile = 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_breakpoint { $$.as_breakpoint = std::move($1); } + | stmt_prof_begin { $$.as_prof_begin = std::move($1); } + | stmt_prof_end { $$.as_prof_end = std::move($1); } + ; + +stmt_or_dev + : stmt { $$ = std::move($1); } + | stmt_dev { $$.as_dev = std::move($1); } + ; + +stmt_list + : stmt_list stmt + { $$ = std::move($1); $$->list.push_back(std::move($2)); } + | stmt + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + ; + +stmt_or_dev_list + : stmt_or_dev_list stmt_or_dev + { $$ = std::move($1); $$->list.push_back(std::move($2)); } + | stmt_or_dev + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + ; + +stmt_dev + : DEVBEGIN stmt_list DEVEND { $$ = std::make_unique(@$, std::move($2)); } + | DEVBEGIN DEVEND { $$ = std::make_unique(@$, std::make_unique(@$)); } + ; + +stmt_block + : LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); } + | LBRACE RBRACE { $$ = std::make_unique(@$); } + ; + +stmt_expr + : expr_assign + { $$ = std::make_unique(@$, std::move($1)); } + | expr_increment + { $$ = std::make_unique(@$, std::move($1)); } + | expr_decrement + { $$ = std::make_unique(@$, std::move($1)); } + | + { $$ = std::make_unique(@$, std::make_unique(@$)); } + ; + +stmt_call + : expr_call SEMICOLON + { $$ = std::make_unique(@$, ast::expr(std::move($1))); } + | expr_method SEMICOLON + { $$ = std::make_unique(@$, ast::expr(std::move($1))); } + ; + +stmt_assign + : expr_assign SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + | expr_increment SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + | expr_decrement SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + ; + +stmt_endon + : expr_object ENDON LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4)); } + ; + +stmt_notify + : expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | expr_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 + : expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | expr_object WAITTILL LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::make_unique(@$)); } + ; + +stmt_waittillmatch + : expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | expr_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_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_dowhile + : DO stmt WHILE LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($5), std::move($2)); } + ; + +stmt_for + : FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt + { $$ = std::make_unique(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); } + ; + +stmt_foreach + : FOREACH LPAREN expr_identifier IN expr RPAREN stmt + { $$ = std::make_unique(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); } + | FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt + { $$ = std::make_unique(@$, ast::expr(std::move($3)), ast::expr(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 expr_integer COLON + { $$ = std::make_unique(@$, ast::expr(std::move($2)), std::make_unique(@$)); } + | CASE expr_string COLON + { $$ = std::make_unique(@$, ast::expr(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(@$)); } + ; + +stmt_breakpoint + : BREAKPOINT SEMICOLON + { $$ = std::make_unique(@$); } + ; + +stmt_prof_begin + : PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($3)); } + ; + +stmt_prof_end + : PROFEND LPAREN expr_arguments RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($3)); } + ; + +expr + : expr_ternary { $$ = std::move($1); } + | expr_binary { $$ = std::move($1); } + | expr_primitive { $$ = std::move($1); } + ; + +expr_or_empty + : expr { $$ = std::move($1); } + | { $$.as_node = std::make_unique(@$); } + ; + +expr_assign + : expr_tuple ASSIGN expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_BW_OR expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_BW_AND expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_BW_EXOR expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_LSHIFT expr + { $$.as_node = std::make_unique(@$, std::move($1),std::move( $3)); } + | expr_object ASSIGN_RSHIFT expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_ADD expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_SUB expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_MUL expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_DIV expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_MOD expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_increment + : INCREMENT expr_object %prec PREINC + { $$.as_node = std::make_unique(@$, std::move($2), true); } + | expr_object INCREMENT %prec POSTINC + { $$.as_node = std::make_unique(@$, std::move($1), false); } + ; + +expr_decrement + : DECREMENT expr_object %prec PREDEC + { $$.as_node = std::make_unique(@$, std::move($2), true); } + | expr_object DECREMENT %prec POSTDEC + { $$.as_node = std::make_unique(@$, std::move($1), false); } + ; + +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 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 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 MUL 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 + : expr_complement { $$.as_node = std::move($1); } + | expr_negate { $$.as_node = std::move($1); } + | expr_not { $$.as_node = std::move($1); } + | expr_call { $$.as_node = std::move($1); } + | expr_method { $$.as_node = std::move($1); } + | expr_add_array { $$.as_node = std::move($1); } + | expr_reference { $$.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); } + | expr_paren { $$.as_node = std::move($1); } + | expr_thisthread { $$.as_node = std::move($1); } + | expr_empty_array { $$.as_node = std::move($1); } + | expr_undefined { $$.as_node = std::move($1); } + | expr_game { $$.as_node = std::move($1); } + | expr_self { $$.as_node = std::move($1); } + | expr_anim { $$.as_node = std::move($1); } + | expr_level { $$.as_node = std::move($1); } + | expr_animation { $$.as_node = std::move($1); } + | expr_animtree { $$.as_node = std::move($1); } + | expr_identifier { $$.as_node = std::move($1); } + | expr_istring { $$.as_node = std::move($1); } + | expr_string { $$.as_node = std::move($1); } + | expr_vector { $$.as_node = std::move($1); } + | expr_float { $$.as_node = std::move($1); } + | expr_integer { $$.as_node = std::move($1); } + | expr_false { $$.as_node = std::move($1); } + | expr_true { $$.as_node = std::move($1); } + ; + +expr_complement + : COMPLEMENT expr + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_negate + : SUB expr_identifier %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + | SUB expr_paren %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + | SUB expr_array %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + | SUB expr_field %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + ; + +expr_not + : NOT expr + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_call + : expr_function { $$ = std::make_unique(@$, std::move($1)); } + | expr_pointer { $$ = std::make_unique(@$, std::move($1)); } + ; +expr_method + : expr_object expr_function { $$ = std::make_unique(@$, std::move($1), std::move($2)); } + | expr_object expr_pointer { $$ = std::make_unique(@$, std::move($1), std::move($2)); } + ; + +expr_function + : expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::make_unique(@$), std::move($1), std::move($3), ast::call::mode::normal); } + | expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); } + | THREAD expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::make_unique(@$), std::move($2), std::move($4), ast::call::mode::thread); } + | THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); } + | CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::make_unique(@$), std::move($2), std::move($4), ast::call::mode::childthread); } + | CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); } + ; + +expr_pointer + : LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($3), std::move($7), ast::call::mode::normal); } + | THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($4), std::move($8), ast::call::mode::thread); } + | CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($4), std::move($8), ast::call::mode::childthread); } + | CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($4), std::move($8), ast::call::mode::builtin); } + ; + +expr_add_array + : LBRACKET expr_arguments_no_empty RBRACKET + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_parameters + : expr_parameters COMMA expr_identifier + { $$ = std::move($1); $$->list.push_back(std::move($3)); } + | expr_identifier + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + | + { $$ = std::make_unique(@$); } + ; + +expr_arguments + : expr_arguments_no_empty + { $$ = std::move($1); } + | + { $$ = std::make_unique(@$); } + ; + +expr_arguments_no_empty + : 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_reference + : DOUBLECOLON expr_identifier + { $$ = std::make_unique(@$, std::make_unique(@$), std::move($2)); } + | expr_path DOUBLECOLON expr_identifier + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_tuple + : LBRACKET expr_tuple_arguments RBRACKET + { $$.as_node = std::move($2); } + ; + +expr_tuple_arguments + : expr_tuple_arguments COMMA expr_tuple_types + { $$ = std::move($1); $$->list.push_back(std::move($3)); } + | expr_tuple_types + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + ; + +expr_tuple_types + : expr_array { $$.as_node = std::move($1); } + | expr_field { $$.as_node = std::move($1); } + | expr_identifier { $$.as_node = std::move($1); } + ; + +expr_array + : expr_object LBRACKET expr RBRACKET + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_field + : expr_object DOT expr_identifier_nosize + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_size + : expr_object DOT SIZE %prec SIZEOF + { $$ = std::make_unique(@$, std::move($1)); } + ; + +expr_paren + : LPAREN expr RPAREN + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_object + : expr_call { $$.as_node = std::move($1); } + | expr_method { $$.as_node = std::move($1); } + | expr_array { $$.as_node = std::move($1); } + | expr_field { $$.as_node = std::move($1); } + | expr_game { $$.as_node = std::move($1); } + | expr_self { $$.as_node = std::move($1); } + | expr_anim { $$.as_node = std::move($1); } + | expr_level { $$.as_node = std::move($1); } + | expr_identifier { $$.as_node = std::move($1); } + ; + +expr_thisthread + : THISTHREAD + { $$ = std::make_unique(@$); }; + ; + +expr_empty_array + : LBRACKET RBRACKET + { $$ = std::make_unique(@$); }; + ; + +expr_undefined + : UNDEFINED + { $$ = std::make_unique(@$); }; + ; + +expr_game + : GAME + { $$ = std::make_unique(@$); }; + ; + +expr_self + : SELF + { $$ = std::make_unique(@$); }; + ; + +expr_anim + : ANIM + { $$ = std::make_unique(@$); }; + ; + +expr_level + : LEVEL + { $$ = std::make_unique(@$); }; + ; + +expr_animation + : MOD IDENTIFIER %prec ANIMREF + { $$ = std::make_unique(@$, $2); }; + ; + +expr_animtree + : ANIMTREE + { $$ = std::make_unique(@$); }; + ; + +expr_identifier_nosize + : IDENTIFIER + { $$ = std::make_unique(@$, $1); }; + ; + +expr_identifier + : IDENTIFIER + { $$ = std::make_unique(@$, $1); }; + | SIZE + { $$ = std::make_unique(@$, "size"); }; + ; + +expr_path + : IDENTIFIER + { $$ = std::make_unique(@$, $1); }; + | PATH + { $$ = std::make_unique(@$, $1); }; + ; + +expr_istring + : ISTRING + { $$ = std::make_unique(@$, $1); }; + ; + +expr_string + : STRING + { $$ = std::make_unique(@$, $1); }; + ; + +expr_vector + : LPAREN expr COMMA expr COMMA expr RPAREN + { $$ = std::make_unique(@$, std::move($2), std::move($4), std::move($6)); }; + ; + +expr_float + : SUB FLOAT %prec NEG + { $$ = std::make_unique(@$, "-" + $2); }; + | FLOAT + { $$ = std::make_unique(@$, $1); }; + ; + +expr_integer + : SUB INTEGER %prec NEG + { $$ = std::make_unique(@$, "-" + $2); }; + | INTEGER + { $$ = std::make_unique(@$, $1); }; + ; + +expr_false + : FALSE + { $$ = std::make_unique(@$); }; + ; + +expr_true + : TRUE + { $$ = std::make_unique(@$); }; + ; + +%% + +void xsk::gsc::iw6c::parser::error(const xsk::gsc::location& loc, const std::string& msg) +{ + throw xsk::gsc::comp_error(loc, msg); +} diff --git a/gen/experimental/s1c/Makefile b/gen/experimental/s1c/Makefile new file mode 100644 index 00000000..d533caf4 --- /dev/null +++ b/gen/experimental/s1c/Makefile @@ -0,0 +1,9 @@ +generate: s1c + +clean: + rm -rf ./parser.hpp + rm -rf ./parser.cpp + +s1c: parser.ypp + bison parser.ypp -Wcounterexamples + mv parser.hpp parser.cpp ../../../src/experimental/s1c/xsk/ diff --git a/gen/experimental/s1c/parser.ypp b/gen/experimental/s1c/parser.ypp new file mode 100644 index 00000000..420aa3e6 --- /dev/null +++ b/gen/experimental/s1c/parser.ypp @@ -0,0 +1,898 @@ +/* Copyright 2022 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 {S1C} +%define api.namespace {xsk::gsc::s1c} +%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 { xsk::gsc::s1c::lexer& lexer } +%parse-param { xsk::gsc::s1c::lexer& lexer } +%parse-param { xsk::gsc::ast::program::ptr& ast } + +%code requires +{ +#ifdef _MSC_VER +#pragma warning(disable:4065) +#pragma warning(disable:4127) +#endif +#include "s1c.hpp" +namespace xsk::gsc::s1c { class lexer; } +} + +%code top +{ +#include "stdafx.hpp" +#include "parser.hpp" +#include "lexer.hpp" +using namespace xsk::gsc; +xsk::gsc::s1c::parser::symbol_type S1Clex(xsk::gsc::s1c::lexer& lexer); +} + +%token SH_DEFINE "#define" +%token SH_UNDEF "#undef" +%token SH_IFDEF "#ifdef" +%token SH_IFNDEF "#ifndef" +%token SH_IF "#if" +%token SH_ELIF "#elif" +%token SH_ELSE "#else" +%token SH_ENDIF "#endif" +%token DEVBEGIN "/#" +%token DEVEND "#/" +%token INLINE "#inline" +%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 DO "do" +%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 BREAKPOINT "breakpoint" +%token PROFBEGIN "prof_begin" +%token PROFEND "prof_end" +%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_MUL "*=" +%token ASSIGN_DIV "/=" +%token ASSIGN_MOD "%=" +%token ASSIGN_BW_OR "|=" +%token ASSIGN_BW_AND "&=" +%token ASSIGN_BW_EXOR "^=" +%token ASSIGN_RSHIFT ">>=" +%token ASSIGN_LSHIFT "<<=" +%token BITWISE_OR "|" +%token BITWISE_AND "&" +%token BITWISE_EXOR "^" +%token ADD "+" +%token SUB "-" +%token MUL "*" +%token DIV "/" +%token MOD "%" +%token PATH "path" +%token IDENTIFIER "identifier" +%token STRING "string literal" +%token ISTRING "localized string" +%token FLOAT "float" +%token INTEGER "integer" + +%type program +%type include +%type declaration +%type decl_usingtree +%type decl_constant +%type decl_thread +%type stmt +%type stmt_or_dev +%type stmt_list +%type stmt_or_dev_list +%type stmt_dev +%type stmt_block +%type stmt_expr +%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_dowhile +%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 stmt_breakpoint +%type stmt_prof_begin +%type stmt_prof_end +%type expr +%type expr_or_empty +%type expr_assign +%type expr_increment +%type expr_decrement +%type expr_ternary +%type expr_binary +%type expr_primitive +%type expr_complement +%type expr_negate +%type expr_not +%type expr_call +%type expr_method +%type expr_function +%type expr_pointer +%type expr_add_array +%type expr_parameters +%type expr_arguments +%type expr_arguments_no_empty +%type expr_reference +%type expr_tuple +%type expr_tuple_arguments +%type expr_tuple_types +%type expr_array +%type expr_field +%type expr_size +%type expr_paren +%type expr_object +%type expr_thisthread +%type expr_empty_array +%type expr_undefined +%type expr_game +%type expr_self +%type expr_anim +%type expr_level +%type expr_animation +%type expr_animtree +%type expr_identifier_nosize +%type expr_identifier +%type expr_path +%type expr_istring +%type expr_string +%type expr_vector +%type expr_float +%type expr_integer +%type expr_false +%type expr_true + +%nonassoc SIZEOF +%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_EXOR +%left BITWISE_AND +%left EQUALITY INEQUALITY +%left LESS GREATER LESS_EQUAL GREATER_EQUAL +%left LSHIFT RSHIFT +%left ADD SUB +%left MUL 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 inline + { $$ = std::move($1); } + | program include + { $$ = std::move($1); $$->includes.push_back(std::move($2)); } + | program declaration + { $$ = std::move($1); $$->declarations.push_back(std::move($2)); } + | inline + { $$ = std::make_unique(@$); } + | include + { $$ = std::make_unique(@$); $$->includes.push_back(std::move($1)); } + | declaration + { $$ = std::make_unique(@$); $$->declarations.push_back(std::move($1)); } + ; + +inline + : INLINE expr_path SEMICOLON { lexer.push_header($2->value); } + ; + +include + : INCLUDE expr_path SEMICOLON + { $$ = std::make_unique(@$, std::move($2)); } + ; + +declaration + : DEVBEGIN { $$.as_dev_begin = std::make_unique(@$); } + | DEVEND { $$.as_dev_end = std::make_unique(@$); } + | decl_usingtree { $$.as_usingtree = std::move($1); } + | decl_constant { $$.as_constant = std::move($1); } + | decl_thread { $$.as_thread = std::move($1); } + ; + +decl_usingtree + : USINGTREE LPAREN expr_string RPAREN SEMICOLON + { lexer.ban_header(@$); $$ = std::make_unique(@$, std::move($3)); } + ; + +decl_constant + : expr_identifier ASSIGN expr SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +decl_thread + : expr_identifier LPAREN expr_parameters RPAREN stmt_block + { lexer.ban_header(@$); $$ = std::make_unique(@$, std::move($1), std::move($3), std::move($5)); } + ; + +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_dowhile { $$.as_dowhile = 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_breakpoint { $$.as_breakpoint = std::move($1); } + | stmt_prof_begin { $$.as_prof_begin = std::move($1); } + | stmt_prof_end { $$.as_prof_end = std::move($1); } + ; + +stmt_or_dev + : stmt { $$ = std::move($1); } + | stmt_dev { $$.as_dev = std::move($1); } + ; + +stmt_list + : stmt_list stmt + { $$ = std::move($1); $$->list.push_back(std::move($2)); } + | stmt + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + ; + +stmt_or_dev_list + : stmt_or_dev_list stmt_or_dev + { $$ = std::move($1); $$->list.push_back(std::move($2)); } + | stmt_or_dev + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + ; + +stmt_dev + : DEVBEGIN stmt_list DEVEND { $$ = std::make_unique(@$, std::move($2)); } + | DEVBEGIN DEVEND { $$ = std::make_unique(@$, std::make_unique(@$)); } + ; + +stmt_block + : LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); } + | LBRACE RBRACE { $$ = std::make_unique(@$); } + ; + +stmt_expr + : expr_assign + { $$ = std::make_unique(@$, std::move($1)); } + | expr_increment + { $$ = std::make_unique(@$, std::move($1)); } + | expr_decrement + { $$ = std::make_unique(@$, std::move($1)); } + | + { $$ = std::make_unique(@$, std::make_unique(@$)); } + ; + +stmt_call + : expr_call SEMICOLON + { $$ = std::make_unique(@$, ast::expr(std::move($1))); } + | expr_method SEMICOLON + { $$ = std::make_unique(@$, ast::expr(std::move($1))); } + ; + +stmt_assign + : expr_assign SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + | expr_increment SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + | expr_decrement SEMICOLON + { $$ = std::make_unique(@$, std::move($1)); } + ; + +stmt_endon + : expr_object ENDON LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4)); } + ; + +stmt_notify + : expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | expr_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 + : expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | expr_object WAITTILL LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::make_unique(@$)); } + ; + +stmt_waittillmatch + : expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($1), std::move($4), std::move($6)); } + | expr_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_dowhile + : DO stmt WHILE LPAREN expr RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($5), std::move($2)); } + ; + +stmt_for + : FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt + { $$ = std::make_unique(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); } + ; + +stmt_foreach + : FOREACH LPAREN expr_identifier IN expr RPAREN stmt + { $$ = std::make_unique(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); } + | FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt + { $$ = std::make_unique(@$, ast::expr(std::move($3)), ast::expr(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 expr_integer COLON + { $$ = std::make_unique(@$, ast::expr(std::move($2)), std::make_unique(@$)); } + | CASE expr_string COLON + { $$ = std::make_unique(@$, ast::expr(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(@$)); } + ; + +stmt_breakpoint + : BREAKPOINT SEMICOLON + { $$ = std::make_unique(@$); } + ; + +stmt_prof_begin + : PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($3)); } + ; + +stmt_prof_end + : PROFEND LPAREN expr_arguments RPAREN SEMICOLON + { $$ = std::make_unique(@$, std::move($3)); } + ; + +expr + : expr_ternary { $$ = std::move($1); } + | expr_binary { $$ = std::move($1); } + | expr_primitive { $$ = std::move($1); } + ; + +expr_or_empty + : expr { $$ = std::move($1); } + | { $$.as_node = std::make_unique(@$); } + ; + +expr_assign + : expr_tuple ASSIGN expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_BW_OR expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_BW_AND expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_BW_EXOR expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_LSHIFT expr + { $$.as_node = std::make_unique(@$, std::move($1),std::move( $3)); } + | expr_object ASSIGN_RSHIFT expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_ADD expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_SUB expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_MUL expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_DIV expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + | expr_object ASSIGN_MOD expr + { $$.as_node = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_increment + : INCREMENT expr_object %prec PREINC + { $$.as_node = std::make_unique(@$, std::move($2), true); } + | expr_object INCREMENT %prec POSTINC + { $$.as_node = std::make_unique(@$, std::move($1), false); } + ; + +expr_decrement + : DECREMENT expr_object %prec PREDEC + { $$.as_node = std::make_unique(@$, std::move($2), true); } + | expr_object DECREMENT %prec POSTDEC + { $$.as_node = std::make_unique(@$, std::move($1), false); } + ; + +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 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 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 MUL 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 + : expr_complement { $$.as_node = std::move($1); } + | expr_negate { $$.as_node = std::move($1); } + | expr_not { $$.as_node = std::move($1); } + | expr_call { $$.as_node = std::move($1); } + | expr_method { $$.as_node = std::move($1); } + | expr_add_array { $$.as_node = std::move($1); } + | expr_reference { $$.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); } + | expr_paren { $$.as_node = std::move($1); } + | expr_thisthread { $$.as_node = std::move($1); } + | expr_empty_array { $$.as_node = std::move($1); } + | expr_undefined { $$.as_node = std::move($1); } + | expr_game { $$.as_node = std::move($1); } + | expr_self { $$.as_node = std::move($1); } + | expr_anim { $$.as_node = std::move($1); } + | expr_level { $$.as_node = std::move($1); } + | expr_animation { $$.as_node = std::move($1); } + | expr_animtree { $$.as_node = std::move($1); } + | expr_identifier { $$.as_node = std::move($1); } + | expr_istring { $$.as_node = std::move($1); } + | expr_string { $$.as_node = std::move($1); } + | expr_vector { $$.as_node = std::move($1); } + | expr_float { $$.as_node = std::move($1); } + | expr_integer { $$.as_node = std::move($1); } + | expr_false { $$.as_node = std::move($1); } + | expr_true { $$.as_node = std::move($1); } + ; + +expr_complement + : COMPLEMENT expr + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_negate + : SUB expr_identifier %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + | SUB expr_paren %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + | SUB expr_array %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + | SUB expr_field %prec NEG + { $$ = std::make_unique(@$, ast::expr(std::move($2))); } + ; + +expr_not + : NOT expr + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_call + : expr_function { $$ = std::make_unique(@$, std::move($1)); } + | expr_pointer { $$ = std::make_unique(@$, std::move($1)); } + ; +expr_method + : expr_object expr_function { $$ = std::make_unique(@$, std::move($1), std::move($2)); } + | expr_object expr_pointer { $$ = std::make_unique(@$, std::move($1), std::move($2)); } + ; + +expr_function + : expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::make_unique(@$), std::move($1), std::move($3), ast::call::mode::normal); } + | expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); } + | THREAD expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::make_unique(@$), std::move($2), std::move($4), ast::call::mode::thread); } + | THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); } + | CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::make_unique(@$), std::move($2), std::move($4), ast::call::mode::childthread); } + | CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN + { $$.as_function = std::make_unique(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); } + ; + +expr_pointer + : LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($3), std::move($7), ast::call::mode::normal); } + | THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($4), std::move($8), ast::call::mode::thread); } + | CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($4), std::move($8), ast::call::mode::childthread); } + | CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN + { $$.as_pointer = std::make_unique(@$, std::move($4), std::move($8), ast::call::mode::builtin); } + ; + +expr_add_array + : LBRACKET expr_arguments_no_empty RBRACKET + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_parameters + : expr_parameters COMMA expr_identifier + { $$ = std::move($1); $$->list.push_back(std::move($3)); } + | expr_identifier + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + | + { $$ = std::make_unique(@$); } + ; + +expr_arguments + : expr_arguments_no_empty + { $$ = std::move($1); } + | + { $$ = std::make_unique(@$); } + ; + +expr_arguments_no_empty + : 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_reference + : DOUBLECOLON expr_identifier + { $$ = std::make_unique(@$, std::make_unique(@$), std::move($2)); } + | expr_path DOUBLECOLON expr_identifier + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_tuple + : LBRACKET expr_tuple_arguments RBRACKET + { $$.as_node = std::move($2); } + ; + +expr_tuple_arguments + : expr_tuple_arguments COMMA expr_tuple_types + { $$ = std::move($1); $$->list.push_back(std::move($3)); } + | expr_tuple_types + { $$ = std::make_unique(@$); $$->list.push_back(std::move($1)); } + ; + +expr_tuple_types + : expr_array { $$.as_node = std::move($1); } + | expr_field { $$.as_node = std::move($1); } + | expr_identifier { $$.as_node = std::move($1); } + ; + +expr_array + : expr_object LBRACKET expr RBRACKET + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_field + : expr_object DOT expr_identifier_nosize + { $$ = std::make_unique(@$, std::move($1), std::move($3)); } + ; + +expr_size + : expr_object DOT SIZE %prec SIZEOF + { $$ = std::make_unique(@$, std::move($1)); } + ; + +expr_paren + : LPAREN expr RPAREN + { $$ = std::make_unique(@$, std::move($2)); } + ; + +expr_object + : expr_call { $$.as_node = std::move($1); } + | expr_method { $$.as_node = std::move($1); } + | expr_array { $$.as_node = std::move($1); } + | expr_field { $$.as_node = std::move($1); } + | expr_game { $$.as_node = std::move($1); } + | expr_self { $$.as_node = std::move($1); } + | expr_anim { $$.as_node = std::move($1); } + | expr_level { $$.as_node = std::move($1); } + | expr_identifier { $$.as_node = std::move($1); } + ; + +expr_thisthread + : THISTHREAD + { $$ = std::make_unique(@$); }; + ; + +expr_empty_array + : LBRACKET RBRACKET + { $$ = std::make_unique(@$); }; + ; + +expr_undefined + : UNDEFINED + { $$ = std::make_unique(@$); }; + ; + +expr_game + : GAME + { $$ = std::make_unique(@$); }; + ; + +expr_self + : SELF + { $$ = std::make_unique(@$); }; + ; + +expr_anim + : ANIM + { $$ = std::make_unique(@$); }; + ; + +expr_level + : LEVEL + { $$ = std::make_unique(@$); }; + ; + +expr_animation + : MOD IDENTIFIER %prec ANIMREF + { $$ = std::make_unique(@$, $2); }; + ; + +expr_animtree + : ANIMTREE + { $$ = std::make_unique(@$); }; + ; + +expr_identifier_nosize + : IDENTIFIER + { $$ = std::make_unique(@$, $1); }; + ; + +expr_identifier + : IDENTIFIER + { $$ = std::make_unique(@$, $1); }; + | SIZE + { $$ = std::make_unique(@$, "size"); }; + ; + +expr_path + : IDENTIFIER + { $$ = std::make_unique(@$, $1); }; + | PATH + { $$ = std::make_unique(@$, $1); }; + ; + +expr_istring + : ISTRING + { $$ = std::make_unique(@$, $1); }; + ; + +expr_string + : STRING + { $$ = std::make_unique(@$, $1); }; + ; + +expr_vector + : LPAREN expr COMMA expr COMMA expr RPAREN + { $$ = std::make_unique(@$, std::move($2), std::move($4), std::move($6)); }; + ; + +expr_float + : SUB FLOAT %prec NEG + { $$ = std::make_unique(@$, "-" + $2); }; + | FLOAT + { $$ = std::make_unique(@$, $1); }; + ; + +expr_integer + : SUB INTEGER %prec NEG + { $$ = std::make_unique(@$, "-" + $2); }; + | INTEGER + { $$ = std::make_unique(@$, $1); }; + ; + +expr_false + : FALSE + { $$ = std::make_unique(@$); }; + ; + +expr_true + : TRUE + { $$ = std::make_unique(@$); }; + ; + +%% + +void xsk::gsc::s1c::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 0770f422..0c03f26b 100644 --- a/premake5.lua +++ b/premake5.lua @@ -62,6 +62,8 @@ project "xsk-gsc-tool" dependson "xsk-gsc-s4" dependson "xsk-arc-t6" dependson "xsk-gsc-iw5c" + dependson "xsk-gsc-iw6c" + dependson "xsk-gsc-s1c" pchheader "stdafx.hpp" pchsource "src/tool/stdafx.cpp" @@ -84,7 +86,9 @@ project "xsk-gsc-tool" "xsk-gsc-s2", "xsk-gsc-s4", "xsk-arc-t6", - "xsk-gsc-iw5c" + "xsk-gsc-iw5c", + "xsk-gsc-iw6c", + "xsk-gsc-s1c" } includedirs { @@ -312,5 +316,41 @@ project "xsk-gsc-iw5c" "./src" } +project "xsk-gsc-iw6c" + kind "StaticLib" + language "C++" + + pchheader "stdafx.hpp" + pchsource "src/experimental/iw6c/stdafx.cpp" + + files { + "./src/experimental/iw6c/**.h", + "./src/experimental/iw6c/**.hpp", + "./src/experimental/iw6c/**.cpp" + } + + includedirs { + "./src/experimental/iw6c", + "./src" + } + +project "xsk-gsc-s1c" + kind "StaticLib" + language "C++" + + pchheader "stdafx.hpp" + pchsource "src/experimental/s1c/stdafx.cpp" + + files { + "./src/experimental/s1c/**.h", + "./src/experimental/s1c/**.hpp", + "./src/experimental/s1c/**.cpp" + } + + includedirs { + "./src/experimental/s1c", + "./src" + } + group "Dependencies" zlib:project() diff --git a/src/experimental/iw5c/xsk/assembler.cpp b/src/experimental/iw5c/xsk/assembler.cpp index 0aaded87..55a2d0cb 100644 --- a/src/experimental/iw5c/xsk/assembler.cpp +++ b/src/experimental/iw5c/xsk/assembler.cpp @@ -128,7 +128,7 @@ void assembler::assemble(const std::string& file, std::vector& fu filename_ = file; functions_ = std::move(funcs); - script_->write(static_cast(opcode::OP_End)); + script_->write_endian(static_cast(opcode::OP_End)); for (const auto& func : functions_) { @@ -158,7 +158,7 @@ void assembler::assemble_function(const function::ptr& func) void assembler::assemble_instruction(const instruction::ptr& inst) { - script_->write(static_cast(inst->opcode)); + script_->write_endian(static_cast(inst->opcode)); switch (static_cast(inst->opcode)) { @@ -254,20 +254,20 @@ void assembler::assemble_instruction(const instruction::ptr& inst) break; case opcode::OP_GetString: case opcode::OP_GetIString: - script_->write(0); + script_->write_endian(0); stack_->write_c_string(inst->data[0]); break; case opcode::OP_GetAnimation: - script_->write(0); + script_->write_endian(0); stack_->write_c_string(inst->data[0]); stack_->write_c_string(inst->data[1]); break; case opcode::OP_GetAnimTree: - script_->write(0); + script_->write_endian(0); stack_->write_c_string(inst->data[0]); break; case opcode::OP_waittillmatch: - script_->write(static_cast(std::stoi(inst->data[0]))); + script_->write_endian(static_cast(std::stoi(inst->data[0]))); break; case opcode::OP_CreateLocalVariable: case opcode::OP_RemoveLocalVariables: @@ -283,7 +283,7 @@ void assembler::assemble_instruction(const instruction::ptr& inst) case opcode::OP_SetLocalVariableFieldCached: case opcode::OP_ClearLocalVariableFieldCached: case opcode::OP_EvalLocalVariableObjectCached: - script_->write(static_cast(std::stoi(inst->data[0]))); + script_->write_endian(static_cast(std::stoi(inst->data[0]))); break; case opcode::OP_EvalLevelFieldVariable: case opcode::OP_EvalAnimFieldVariable: @@ -305,7 +305,7 @@ void assembler::assemble_instruction(const instruction::ptr& inst) case opcode::OP_ScriptMethodChildThreadCallPointer: case opcode::OP_CallBuiltinPointer: case opcode::OP_CallBuiltinMethodPointer: - script_->write(static_cast(std::stoi(inst->data[0]))); + script_->write_endian(static_cast(std::stoi(inst->data[0]))); break; case opcode::OP_ScriptLocalFunctionCall2: case opcode::OP_ScriptLocalFunctionCall: @@ -382,7 +382,7 @@ void assembler::assemble_builtin_call(const instruction::ptr& inst, bool method, { if (args) { - script_->write(static_cast(std::stoi(inst->data[1]))); + script_->write_endian(static_cast(std::stoi(inst->data[1]))); } const auto id = method ? resolver::method_id(inst->data[0]) : resolver::function_id(inst->data[0]); @@ -399,18 +399,18 @@ void assembler::assemble_local_call(const instruction::ptr& inst, bool thread) if (thread) { - script_->write(static_cast(std::stoi(inst->data[1]))); + script_->write_endian(static_cast(std::stoi(inst->data[1]))); } } void assembler::assemble_far_call(const instruction::ptr& inst, bool thread) { - script_->write(0); - script_->write(0); + script_->write_endian(0); + script_->write_endian(0); if (thread) { - script_->write(static_cast(std::stoi(inst->data[2]))); + script_->write_endian(static_cast(std::stoi(inst->data[2]))); } const auto file_id = resolver::token_id(inst->data[0]); @@ -489,7 +489,7 @@ void assembler::assemble_field_variable(const instruction::ptr& inst) if (id > max_string_id) { - stack_->write(0); + stack_->write_endian(0); stack_->write_c_string(inst->data[0]); } } @@ -520,9 +520,9 @@ void assembler::assemble_offset(std::int32_t offset) *reinterpret_cast(bytes.data()) = offset; - script_->write(bytes[2]); - script_->write(bytes[1]); - script_->write(bytes[0]); + script_->write_endian(bytes[2]); + script_->write_endian(bytes[1]); + script_->write_endian(bytes[0]); } auto assembler::resolve_function(const std::string& name) -> std::int32_t diff --git a/src/experimental/iw5c/xsk/disassembler.cpp b/src/experimental/iw5c/xsk/disassembler.cpp index 7f77aad7..04a8b31a 100644 --- a/src/experimental/iw5c/xsk/disassembler.cpp +++ b/src/experimental/iw5c/xsk/disassembler.cpp @@ -72,7 +72,7 @@ void disassembler::dissasemble_function(const function::ptr& func) const auto& inst = func->instructions.back(); inst->index = static_cast(script_->pos()); - inst->opcode = script_->read(); + inst->opcode = script_->read_endian(); inst->size = opcode_size(inst->opcode); dissasemble_instruction(inst); @@ -157,7 +157,7 @@ void disassembler::dissasemble_instruction(const instruction::ptr& inst) break; case opcode::OP_GetByte: case opcode::OP_GetNegByte: - inst->data.push_back(utils::string::va("%i", script_->read())); + inst->data.push_back(utils::string::va("%i", script_->read_endian())); break; case opcode::OP_GetUnsignedShort: case opcode::OP_GetNegUnsignedShort: @@ -190,7 +190,7 @@ void disassembler::dissasemble_instruction(const instruction::ptr& inst) inst->data.push_back(utils::string::quote(stack_->read_c_string(), false)); break; case opcode::OP_waittillmatch: - inst->data.push_back(utils::string::va("%i", script_->read())); + inst->data.push_back(utils::string::va("%i", script_->read_endian())); break; case opcode::OP_CreateLocalVariable: case opcode::OP_RemoveLocalVariables: @@ -206,7 +206,7 @@ void disassembler::dissasemble_instruction(const instruction::ptr& inst) case opcode::OP_SetLocalVariableFieldCached: case opcode::OP_ClearLocalVariableFieldCached: case opcode::OP_EvalLocalVariableObjectCached: - inst->data.push_back(utils::string::va("%i", script_->read())); + inst->data.push_back(utils::string::va("%i", script_->read_endian())); break; case opcode::OP_EvalLevelFieldVariable: case opcode::OP_EvalAnimFieldVariable: @@ -228,7 +228,7 @@ void disassembler::dissasemble_instruction(const instruction::ptr& inst) case opcode::OP_ScriptMethodChildThreadCallPointer: case opcode::OP_CallBuiltinPointer: case opcode::OP_CallBuiltinMethodPointer: - inst->data.push_back(utils::string::va("%i", script_->read())); + inst->data.push_back(utils::string::va("%i", script_->read_endian())); break; case opcode::OP_GetLocalFunction: case opcode::OP_ScriptLocalFunctionCall2: @@ -305,7 +305,7 @@ void disassembler::disassemble_builtin_call(const instruction::ptr& inst, bool m { if (args) { - inst->data.push_back(utils::string::va("%i", script_->read())); + inst->data.push_back(utils::string::va("%i", script_->read_endian())); } const auto id = script_->read_endian(); @@ -321,7 +321,7 @@ void disassembler::disassemble_local_call(const instruction::ptr& inst, bool thr if (thread) { - inst->data.push_back(utils::string::va("%i", script_->read())); + inst->data.push_back(utils::string::va("%i", script_->read_endian())); } } @@ -331,7 +331,7 @@ void disassembler::disassemble_far_call(const instruction::ptr& inst, bool threa if (thread) { - inst->data.push_back(utils::string::va("%i", script_->read())); + inst->data.push_back(utils::string::va("%i", script_->read_endian())); } const auto file_id = stack_->read_endian(); @@ -444,7 +444,7 @@ auto disassembler::disassemble_offset() -> std::int32_t for (auto i = 0; i < 3; i++) { - bytes[2 - i] = script_->read(); + bytes[2 - i] = script_->read_endian(); } auto offset = *reinterpret_cast(bytes.data()); diff --git a/src/experimental/iw6_console/xsk/iw6_console.cpp b/src/experimental/iw6_console/xsk/iw6_console.cpp deleted file mode 100644 index 0cf101f8..00000000 --- a/src/experimental/iw6_console/xsk/iw6_console.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2022 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 "iw6_console.hpp" - -namespace xsk::gsc::iw6_console -{ - -auto opcode_size(std::uint8_t id) -> std::uint32_t -{ - switch (opcode(id)) - { - case opcode::OP_End: - case opcode::OP_Return: - case opcode::OP_GetUndefined: - case opcode::OP_GetZero: - case opcode::OP_waittillFrameEnd: - 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_EvalArray: - case opcode::OP_EvalArrayRef: - case opcode::OP_EvalLocalArrayRefCached0: - case opcode::OP_ClearArray: - case opcode::OP_EmptyArray: - case opcode::OP_AddArray: - case opcode::OP_PreScriptCall: - case opcode::OP_ScriptFunctionCallPointer: - case opcode::OP_ScriptMethodCallPointer: - case opcode::OP_GetLevelObject: - case opcode::OP_GetAnimObject: - case opcode::OP_GetSelf: - case opcode::OP_GetThisthread: - case opcode::OP_GetLevel: - case opcode::OP_GetGame: - case opcode::OP_GetAnim: - case opcode::OP_GetGameRef: - case opcode::OP_inc: - case opcode::OP_dec: - case opcode::OP_bit_or: - case opcode::OP_bit_ex_or: - case opcode::OP_bit_and: - case opcode::OP_equality: - case opcode::OP_inequality: - case opcode::OP_less: - case opcode::OP_greater: - case opcode::OP_less_equal: -// case opcode::OP_waittillmatch2: - case opcode::OP_waittill: - case opcode::OP_notify: - case opcode::OP_endon: - case opcode::OP_voidCodepos: - case opcode::OP_vector: - case opcode::OP_greater_equal: - case opcode::OP_shift_left: - case opcode::OP_shift_right: - case opcode::OP_plus: - case opcode::OP_minus: - case opcode::OP_multiply: - case opcode::OP_divide: - case opcode::OP_mod: - case opcode::OP_size: - case opcode::OP_GetSelfObject: - case opcode::OP_SafeSetVariableFieldCached0: - case opcode::OP_clearparams: - case opcode::OP_checkclearparams: - case opcode::OP_EvalLocalVariableRefCached0: -// case opcode::OP_EvalNewLocalVariableRefCached0: - case opcode::OP_SetVariableField: -// case opcode::OP_ClearVariableField: - case opcode::OP_SetLocalVariableFieldCached0: - case opcode::OP_ClearLocalVariableFieldCached0: - case opcode::OP_wait: - case opcode::OP_DecTop: - case opcode::OP_CastFieldObject: - case opcode::OP_CastBool: - case opcode::OP_BoolNot: - case opcode::OP_BoolComplement: - return 1; - case opcode::OP_GetByte: - case opcode::OP_GetNegByte: - case opcode::OP_CreateLocalVariable: - case opcode::OP_RemoveLocalVariables: - case opcode::OP_EvalLocalVariableCached: - case opcode::OP_EvalLocalArrayCached: - case opcode::OP_EvalNewLocalArrayRefCached0: - case opcode::OP_EvalLocalArrayRefCached: - case opcode::OP_ScriptThreadCallPointer: - case opcode::OP_ScriptMethodThreadCallPointer: - case opcode::OP_ScriptMethodChildThreadCallPointer: - case opcode::OP_CallBuiltinPointer: - case opcode::OP_CallBuiltinMethodPointer: - case opcode::OP_SafeCreateVariableFieldCached: - case opcode::OP_SafeSetVariableFieldCached: - case opcode::OP_SafeSetWaittillVariableFieldCached: - case opcode::OP_GetAnimTree: - case opcode::OP_EvalLocalVariableRefCached: - case opcode::OP_SetNewLocalVariableFieldCached0: - case opcode::OP_SetLocalVariableFieldCached: - case opcode::OP_ClearLocalVariableFieldCached: - case opcode::OP_EvalLocalVariableObjectCached: - return 2; - case opcode::OP_GetUnsignedShort: - case opcode::OP_GetNegUnsignedShort: - case opcode::OP_GetBuiltinFunction: - case opcode::OP_GetBuiltinMethod: - case opcode::OP_GetString: - case opcode::OP_GetIString: - case opcode::OP_JumpOnFalseExpr: - case opcode::OP_JumpOnTrueExpr: - case opcode::OP_jumpback: - case opcode::OP_endswitch: - case opcode::OP_JumpOnFalse: - case opcode::OP_JumpOnTrue: - case opcode::OP_waittillmatch: - case opcode::OP_EvalLevelFieldVariable: - case opcode::OP_EvalAnimFieldVariable: - case opcode::OP_EvalSelfFieldVariable: - case opcode::OP_EvalFieldVariable: - case opcode::OP_EvalLevelFieldVariableRef: - case opcode::OP_EvalAnimFieldVariableRef: - case opcode::OP_EvalSelfFieldVariableRef: - case opcode::OP_EvalFieldVariableRef: - case opcode::OP_ClearFieldVariable: - case opcode::OP_SetLevelFieldVariableField: - case opcode::OP_SetAnimFieldVariableField: - case opcode::OP_SetSelfFieldVariableField: - 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_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_ScriptLocalFunctionCall2: - case opcode::OP_ScriptLocalFunctionCall: - case opcode::OP_ScriptLocalMethodCall: - case opcode::OP_GetLocalFunction: - case opcode::OP_CallBuiltin: - case opcode::OP_CallBuiltinMethod: - case opcode::OP_ScriptFarFunctionCall2: - case opcode::OP_ScriptFarFunctionCall: - case opcode::OP_ScriptFarMethodCall: - case opcode::OP_GetFarFunction: - return 4; - case opcode::OP_GetInteger: - case opcode::OP_GetFloat: - case opcode::OP_ScriptLocalThreadCall: - case opcode::OP_ScriptLocalChildThreadCall: - case opcode::OP_ScriptLocalMethodThreadCall: - case opcode::OP_ScriptLocalMethodChildThreadCall: - case opcode::OP_ScriptFarThreadCall: - case opcode::OP_ScriptFarChildThreadCall: - case opcode::OP_ScriptFarMethodThreadCall: - case opcode::OP_ScriptFarMethodChildThreadCall: - case opcode::OP_GetAnimation: - case opcode::OP_switch: - case opcode::OP_jump: - return 5; - case opcode::OP_GetVector: - return 13; - default: - throw std::runtime_error("Couldn't resolve instruction size for " + std::to_string(id)); - } -} - -} // namespace xsk::gsc::iw6_console diff --git a/src/experimental/iw6_console/stdafx.cpp b/src/experimental/iw6c/stdafx.cpp similarity index 100% rename from src/experimental/iw6_console/stdafx.cpp rename to src/experimental/iw6c/stdafx.cpp diff --git a/src/experimental/iw6_console/stdafx.hpp b/src/experimental/iw6c/stdafx.hpp similarity index 100% rename from src/experimental/iw6_console/stdafx.hpp rename to src/experimental/iw6c/stdafx.hpp diff --git a/src/experimental/iw6c/xsk/assembler.cpp b/src/experimental/iw6c/xsk/assembler.cpp new file mode 100644 index 00000000..067abb98 --- /dev/null +++ b/src/experimental/iw6c/xsk/assembler.cpp @@ -0,0 +1,555 @@ +// Copyright 2022 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 "iw6c.hpp" + +namespace xsk::gsc::iw6c +{ + +auto assembler::output_script() -> std::vector +{ + std::vector script; + + if (script_ == nullptr) return script; + + script.resize(script_->pos()); + std::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()); + std::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; + 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 opdata = utils::string::parse_code(line); + + if (switchnum) + { + if (opdata[0] == "case" || opdata[0] == "default") + { + for (auto& entry : opdata) + { + func->instructions.back()->data.push_back(entry); + } + switchnum--; + continue; + } + + throw asm_error("invalid instruction inside endswitch \""s + line + "\"!"); + } + else + { + auto inst = std::make_unique(); + inst->index = index; + inst->opcode = resolver::opcode_id(opdata[0]); + inst->size = opcode_size(inst->opcode); + opdata.erase(opdata.begin()); + inst->data = std::move(opdata); + + switch (static_cast(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[0] = inst->data[0].substr(4); + break; + case opcode::OP_endswitch: + switchnum = static_cast(std::stoi(inst->data[0])); + inst->size += 7 * switchnum; + break; + default: + break; + } + + index += inst->size; + func->instructions.push_back(std::move(inst)); + } + } + } + + assemble(file, functions); +} + +void assembler::assemble(const std::string& file, std::vector& funcs) +{ + script_ = std::make_unique(0x100000); + stack_ = std::make_unique(0x100000); + filename_ = file; + functions_ = std::move(funcs); + + script_->write_endian(static_cast(opcode::OP_End)); + + for (const auto& func : functions_) + { + assemble_function(func); + } +} + +void assembler::assemble_function(const function::ptr& func) +{ + labels_ = func->labels; + + func->id = resolver::token_id(func->name); + + stack_->write_endian(func->size); + stack_->write_endian(static_cast(func->id)); + + if (func->id == 0) + { + stack_->write_c_string(func->name); + } + + for (const auto& inst : func->instructions) + { + assemble_instruction(inst); + } +} + +void assembler::assemble_instruction(const instruction::ptr& inst) +{ + script_->write_endian(static_cast(inst->opcode)); + + switch (static_cast(inst->opcode)) + { + case opcode::OP_Return: + case opcode::OP_BoolNot: + case opcode::OP_CastBool: + case opcode::OP_inequality: + case opcode::OP_GetThisthread: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_checkclearparams: + case opcode::OP_CastFieldObject: + case opcode::OP_End: + case opcode::OP_size: + case opcode::OP_EmptyArray: + case opcode::OP_bit_and: + case opcode::OP_less_equal: + case opcode::OP_voidCodepos: +// case opcode::OP_ClearVariableField: + case opcode::OP_divide: + case opcode::OP_GetSelf: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_plus: + case opcode::OP_BoolComplement: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_inc: + case opcode::OP_clearparams: + case opcode::OP_EvalLocalVariableRefCached0: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_endon: + case opcode::OP_greater_equal: + case opcode::OP_GetSelfObject: + case opcode::OP_SetVariableField: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_less: + case opcode::OP_GetGameRef: + case opcode::OP_waittillFrameEnd: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_GetLevel: + case opcode::OP_notify: + case opcode::OP_DecTop: + case opcode::OP_shift_left: + case opcode::OP_greater: + 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_GetZero: + case opcode::OP_wait: + case opcode::OP_minus: +// case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_multiply: + case opcode::OP_mod: + case opcode::OP_GetGame: + case opcode::OP_waittill: + case opcode::OP_dec: + case opcode::OP_PreScriptCall: + case opcode::OP_GetAnim: + case opcode::OP_GetUndefined: + case opcode::OP_GetAnimObject: + case opcode::OP_GetLevelObject: + case opcode::OP_bit_ex_or: + case opcode::OP_equality: + case opcode::OP_ClearArray: + case opcode::OP_EvalArrayRef: + case opcode::OP_EvalArray: + case opcode::OP_vector: + case opcode::OP_bit_or: + case opcode::OP_AddArray: +/// case opcode::OP_waittillmatch2: + case opcode::OP_shift_right: + break; + case opcode::OP_GetByte: + case opcode::OP_GetNegByte: + script_->write_endian(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetUnsignedShort: + case opcode::OP_GetNegUnsignedShort: + script_->write_endian(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetInteger: + script_->write_endian(std::stoi(inst->data[0])); + break; + case opcode::OP_GetFloat: + script_->write_endian(std::stof(inst->data[0])); + break; + case opcode::OP_GetVector: + inst->size += script_->align(4); + script_->write_endian(std::stof(inst->data[0])); + script_->write_endian(std::stof(inst->data[1])); + script_->write_endian(std::stof(inst->data[2])); + break; + case opcode::OP_GetString: + case opcode::OP_GetIString: + script_->write_endian(0); + stack_->write_c_string(inst->data[0]); + break; + case opcode::OP_GetAnimation: + script_->write_endian(0); + script_->write_endian(0); + stack_->write_c_string(inst->data[0]); + stack_->write_c_string(inst->data[1]); + break; + case opcode::OP_GetAnimTree: + script_->write_endian(0); + stack_->write_c_string(inst->data[0]); + break; + case opcode::OP_waittillmatch: + script_->write_endian(static_cast(std::stoi(inst->data[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_endian(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: + 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_endian(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalMethodCall: + assemble_local_call(inst, false); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + assemble_local_call(inst, true); + break; + case opcode::OP_GetFarFunction: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarMethodCall: + assemble_far_call(inst, false); + break; + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_ScriptFarMethodChildThreadCall: + assemble_far_call(inst, true); + break; + case opcode::OP_CallBuiltin: + assemble_builtin_call(inst, false, true); + break; + case opcode::OP_CallBuiltinMethod: + 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: + 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: + assemble_builtin_call(inst, true, false); + break; + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + assemble_jump(inst, true, false); + break; + case opcode::OP_jumpback: + assemble_jump(inst, false, true); + break; + case opcode::OP_jump: + assemble_jump(inst, false, false); + break; + case opcode::OP_switch: + assemble_switch(inst); + break; + case opcode::OP_endswitch: + assemble_end_switch(inst); + break; + default: + throw asm_error(utils::string::va("unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index)); + } +} + +void assembler::assemble_builtin_call(const instruction::ptr& inst, bool method, bool args) +{ + if (args) + { + script_->write_endian(static_cast(std::stoi(inst->data[1]))); + } + + const auto id = method ? resolver::method_id(inst->data[0]) : resolver::function_id(inst->data[0]); + + script_->write_endian(id); +} + +void assembler::assemble_local_call(const instruction::ptr& inst, bool thread) +{ + const auto addr = resolve_function(inst->data[0]); + const auto offset = static_cast(addr - inst->index - 1); + + assemble_offset(offset); + + if (thread) + { + script_->write_endian(static_cast(std::stoi(inst->data[1]))); + } +} + +void assembler::assemble_far_call(const instruction::ptr& inst, bool thread) +{ + script_->write_endian(0); + script_->write_endian(0); + + if (thread) + { + script_->write_endian(static_cast(std::stoi(inst->data[2]))); + } + + const auto file_id = resolver::token_id(inst->data[0]); + const auto func_id = resolver::token_id(inst->data[1]); + + stack_->write_endian(file_id); + if (file_id == 0) stack_->write_c_string(inst->data[0]); + stack_->write_endian(func_id); + if (func_id == 0) stack_->write_c_string(inst->data[1]); +} + +void assembler::assemble_switch(const instruction::ptr& inst) +{ + const auto addr = resolve_label(inst->data[0]); + + script_->write_endian(addr - inst->index - 4); +} + +void assembler::assemble_end_switch(const instruction::ptr& inst) +{ + const auto count = std::stoul(inst->data[0]); + + script_->write_endian(static_cast(count)); + + std::uint32_t index = inst->index + 3; + + for (auto i = 0u; i < count; i++) + { + if (inst->data[1 + (3 * i)] == "case") + { + if (utils::string::is_number(inst->data[1 + (3 * i) + 1])) + { + script_->write_endian((std::stoi(inst->data[1 + (3 * i) + 1]) & 0xFFFFFF) + 0x800000); + } + else + { + script_->write_endian(i + 1); + stack_->write_c_string(inst->data[1 + (3 * i) + 1]); + } + + index += 4; + + const auto addr = resolve_label(inst->data[1 + (3 * i) + 2]); + + assemble_offset(addr - index); + + index += 3; + } + else if (inst->data[1 + (3 * i)] == "default") + { + script_->write_endian(0); + stack_->write_c_string("\x01"); + + index += 4; + + const auto addr = resolve_label(inst->data[1 + (3 * i) + 1]); + + assemble_offset(addr - index); + + index += 3; + } + else + { + throw asm_error("invalid switch case '" + inst->data[1 + (3 * i)] + "'!"); + } + } +} + +void assembler::assemble_field_variable(const instruction::ptr& inst) +{ + auto id = resolver::token_id(inst->data[0]); + + if (id == 0) id = 0xFFFF; + + script_->write_endian(id); + + if (id > max_string_id) + { + stack_->write_endian(0); + stack_->write_c_string(inst->data[0]); + } +} + +void assembler::assemble_jump(const instruction::ptr& inst, bool expr, bool back) +{ + const auto addr = resolve_label(inst->data[0]); + + if (expr) + { + script_->write_endian(static_cast(addr - inst->index - 3)); + } + else if (back) + { + script_->write_endian(static_cast((inst->index + 3) - addr)); + } + else + { + script_->write_endian(static_cast(addr - inst->index - 5)); + } +} + +void assembler::assemble_offset(std::int32_t offset) +{ + std::array bytes = {}; + + offset = (offset << 10) >> 8; + + *reinterpret_cast(bytes.data()) = offset; + + script_->write_endian(bytes[2]); + script_->write_endian(bytes[1]); + script_->write_endian(bytes[0]); +} + +auto assembler::resolve_function(const std::string& name) -> std::int32_t +{ + for (const auto& entry : functions_) + { + if (entry->name == name) + { + return entry->index; + } + } + + throw asm_error("couldn't resolve local function address of '" + name + "'!"); +} + +auto assembler::resolve_label(const std::string& name) -> std::int32_t +{ + for (const auto& entry : labels_) + { + if (entry.second == name) + { + return entry.first; + } + } + + throw asm_error("couldn't resolve label address of '" + name + "'!"); +} + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/assembler.hpp b/src/experimental/iw6c/xsk/assembler.hpp new file mode 100644 index 00000000..907a16c3 --- /dev/null +++ b/src/experimental/iw6c/xsk/assembler.hpp @@ -0,0 +1,40 @@ +// Copyright 2022 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::iw6c +{ + +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& funcs); + +private: + void assemble_function(const function::ptr& func); + void assemble_instruction(const instruction::ptr& inst); + void assemble_builtin_call(const instruction::ptr& inst, bool method, bool args); + void assemble_local_call(const instruction::ptr& inst, bool thread); + void assemble_far_call(const instruction::ptr& inst, bool thread); + void assemble_switch(const instruction::ptr& inst); + void assemble_end_switch(const instruction::ptr& inst); + void assemble_field_variable(const instruction::ptr& inst); + void assemble_jump(const instruction::ptr& inst, bool expr, bool back); + void assemble_offset(std::int32_t offset); + auto resolve_function(const std::string& name) -> std::int32_t; + auto resolve_label(const std::string& name) -> std::int32_t; +}; + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/compiler.cpp b/src/experimental/iw6c/xsk/compiler.cpp new file mode 100644 index 00000000..bb3d3c9c --- /dev/null +++ b/src/experimental/iw6c/xsk/compiler.cpp @@ -0,0 +1,2966 @@ +// Copyright 2022 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 "iw6c.hpp" +#include "parser.hpp" +#include "lexer.hpp" + +namespace xsk::gsc::iw6c +{ + +auto compiler::output() -> std::vector +{ + return std::move(assembly_); +} + +void compiler::compile(const std::string& file, std::vector& data) +{ + filename_ = file; + + auto prog = parse_buffer(filename_, reinterpret_cast(data.data()), data.size()); + + compile_program(prog); +} + +void compiler::mode(build mode) +{ + mode_ = mode; +} + +auto compiler::parse_buffer(const std::string& file, const char* data, size_t size) -> ast::program::ptr +{ + ast::program::ptr result(nullptr); + + lexer lexer(mode_, file, data, size); + + parser parser(lexer, result); + + if (parser.parse() || result == nullptr) + { + throw comp_error(location(&file), "an unknown error ocurred while parsing gsc file"); + } + + return result; +} + +auto compiler::parse_file(const std::string& file) -> ast::program::ptr +{ + auto data = resolver::file_data(file); + + return parse_buffer(file, std::get<1>(data), std::get<2>(data)); +} + +void compiler::compile_program(const ast::program::ptr& program) +{ + assembly_.clear(); + includes_.clear(); + animtrees_.clear(); + constants_.clear(); + local_functions_.clear(); + index_ = 1; + developer_thread_ = false; + + for (const auto& entry : program->declarations) + { + if (entry == ast::kind::decl_thread) + { + local_functions_.push_back(entry.as_thread->name->value); + } + } + + for (const auto& include : program->includes) + { + emit_include(include); + } + + for (const auto& declaration : program->declarations) + { + emit_declaration(declaration); + } +} + +void compiler::emit_include(const ast::include::ptr& include) +{ + const auto& path = include->path->value; + + for (const auto& inc : includes_) + { + if (inc.name == path) + { + throw comp_error(include->loc(), "duplicated include file '" + path + "'"); + } + } + + if (map_known_includes(path)) return; + + try + { + auto program = parse_file(path); + + std::vector funcs; + + for (const auto& decl : program->declarations) + { + if (decl == ast::kind::decl_thread) + { + funcs.push_back(decl.as_thread->name->value); + } + } + + if (funcs.size() == 0) + { + throw comp_error(include->loc(), "empty include file '" + path + "'"); + } + + includes_.push_back(include_t(path, funcs)); + } + catch (const std::exception& e) + { + throw comp_error(include->loc(), "error parsing include file '" + path + "': " + e.what()); + } +} + +void compiler::emit_declaration(const ast::decl& decl) +{ + switch (decl.kind()) + { + case ast::kind::decl_dev_begin: + developer_thread_ = true; + break; + case ast::kind::decl_dev_end: + developer_thread_ = false; + break; + case ast::kind::decl_usingtree: + emit_decl_usingtree(decl.as_usingtree); + break; + case ast::kind::decl_constant: + emit_decl_constant(decl.as_constant); + break; + case ast::kind::decl_thread: + emit_decl_thread(decl.as_thread); + break; + default: + throw comp_error(decl.loc(), "unknown declaration"); + } +} + +void compiler::emit_decl_usingtree(const ast::decl_usingtree::ptr& animtree) +{ + if (developer_thread_) + throw comp_error(animtree->loc(), "cannot put #using_animtree inside developer block comment"); + + animtrees_.push_back({ animtree->name->value, false }); +} + +void compiler::emit_decl_constant(const ast::decl_constant::ptr& constant) +{ + const auto itr = constants_.find(constant->name->value); + + if (itr != constants_.end()) + throw comp_error(constant->loc(), "duplicated constant '" + constant->name->value + "'"); + + constants_.insert({ constant->name->value, std::move(constant->value) }); +} + +void compiler::emit_decl_thread(const ast::decl_thread::ptr& thread) +{ + function_ = std::make_unique(); + function_->index = index_; + function_->name = thread->name->value; + + auto blk = std::make_unique(); + stack_idx_ = 0; + label_idx_ = 0; + can_break_ = false; + can_continue_ = false; + local_stack_.clear(); + break_blks_.clear(); + continue_blks_.clear(); + + process_thread(thread, blk); + + emit_expr_parameters(thread->params, blk); + emit_stmt_list(thread->stmt, blk, true); + emit_opcode(opcode::OP_End); + + function_->size = index_ - function_->index; + assembly_.push_back(std::move(function_)); +} + +void compiler::emit_stmt(const ast::stmt& stmt, const block::ptr& blk, bool last) +{ + switch (stmt.kind()) + { + case ast::kind::stmt_list: + emit_stmt_list(stmt.as_list, blk, last); + break; + case ast::kind::stmt_dev: + emit_stmt_dev(stmt.as_dev, blk, last); + break; + case ast::kind::stmt_expr: + emit_stmt_expr(stmt.as_expr, blk); + break; + case ast::kind::stmt_call: + emit_stmt_call(stmt.as_call, blk); + break; + case ast::kind::stmt_assign: + emit_stmt_assign(stmt.as_assign, blk); + break; + case ast::kind::stmt_endon: + emit_stmt_endon(stmt.as_endon, blk); + break; + case ast::kind::stmt_notify: + emit_stmt_notify(stmt.as_notify, blk); + break; + case ast::kind::stmt_wait: + emit_stmt_wait(stmt.as_wait, blk); + break; + case ast::kind::stmt_waittill: + emit_stmt_waittill(stmt.as_waittill, blk); + break; + case ast::kind::stmt_waittillmatch: + emit_stmt_waittillmatch(stmt.as_waittillmatch, blk); + break; + case ast::kind::stmt_waittillframeend: + emit_stmt_waittillframeend(stmt.as_waittillframeend, blk); + break; + case ast::kind::stmt_if: + emit_stmt_if(stmt.as_if, blk, last); + break; + case ast::kind::stmt_ifelse: + emit_stmt_ifelse(stmt.as_ifelse, blk, last); + break; + case ast::kind::stmt_while: + emit_stmt_while(stmt.as_while, blk); + break; + case ast::kind::stmt_dowhile: + emit_stmt_dowhile(stmt.as_dowhile, blk); + break; + case ast::kind::stmt_for: + emit_stmt_for(stmt.as_for, blk); + break; + case ast::kind::stmt_foreach: + emit_stmt_foreach(stmt.as_foreach, blk); + break; + case ast::kind::stmt_switch: + emit_stmt_switch(stmt.as_switch, blk); + break; + case ast::kind::stmt_case: + emit_stmt_case(stmt.as_case, blk); + break; + case ast::kind::stmt_default: + emit_stmt_default(stmt.as_default, blk); + break; + case ast::kind::stmt_break: + emit_stmt_break(stmt.as_break, blk); + break; + case ast::kind::stmt_continue: + emit_stmt_continue(stmt.as_continue, blk); + break; + case ast::kind::stmt_return: + emit_stmt_return(stmt.as_return, blk); + break; + case ast::kind::stmt_breakpoint: + emit_stmt_breakpoint(stmt.as_breakpoint, blk); + break; + case ast::kind::stmt_prof_begin: + emit_stmt_prof_begin(stmt.as_prof_begin, blk); + break; + case ast::kind::stmt_prof_end: + emit_stmt_prof_end(stmt.as_prof_end, blk); + break; + default: + throw comp_error(stmt.loc(), "unknown statement"); + } +} + +void compiler::emit_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk, bool last) +{ + for (const auto& entry : stmt->list) + { + bool last_ = (&entry == &stmt->list.back() && last) ? true : false; + emit_stmt(entry, blk, last_); + } +} + +void compiler::emit_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk, bool last) +{ + emit_stmt_list(stmt->list, blk, last); +} + +void compiler::emit_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + emit_expr_increment(stmt->expr.as_increment, blk, true); + break; + case ast::kind::expr_decrement: + emit_expr_decrement(stmt->expr.as_decrement, blk, true); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + emit_expr_assign(stmt->expr.as_assign, blk); + break; + case ast::kind::null: + break; + default: + throw comp_error(stmt->loc(), "unknown expr statement expression"); + } +} + +void compiler::emit_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk) +{ + if (stmt->expr == ast::kind::expr_call) + emit_expr_call(stmt->expr.as_call, blk, true); + else if (stmt->expr == ast::kind::expr_method) + emit_expr_method(stmt->expr.as_method, blk, true); + else + throw comp_error(stmt->loc(), "unknown call statement expression"); +} + +void compiler::emit_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + emit_expr_increment(stmt->expr.as_increment, blk, true); + break; + case ast::kind::expr_decrement: + emit_expr_decrement(stmt->expr.as_decrement, blk, true); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + emit_expr_assign(stmt->expr.as_assign, blk); + break; + default: + throw comp_error(stmt->loc(), "unknown assign statement expression"); + } +} + +void compiler::emit_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk) +{ + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_endon); +} + +void compiler::emit_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk) +{ + emit_opcode(opcode::OP_voidCodepos); + + std::reverse(stmt->args->list.begin(), stmt->args->list.end()); + + for (const auto& arg : stmt->args->list) + { + emit_expr(arg, blk); + } + + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_notify); +} + +void compiler::emit_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk) +{ + emit_expr(stmt->time, blk); + emit_opcode(opcode::OP_wait); +} + +void compiler::emit_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk) +{ + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_waittill); + + for (const auto& entry : stmt->args->list) + { + variable_create(entry.as_identifier, blk); + emit_opcode(opcode::OP_SafeSetWaittillVariableFieldCached, variable_access_index(entry.as_identifier, blk)); + } + + emit_opcode(opcode::OP_clearparams); +} + +void compiler::emit_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk) +{ + emit_expr_arguments(stmt->args, blk); + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_waittillmatch, utils::string::va("%d", stmt->args->list.size())); +// emit_opcode(opcode::OP_waittillmatch2); +// TODOOO! + emit_opcode(opcode::OP_clearparams); +} + +void compiler::emit_stmt_waittillframeend(const ast::stmt_waittillframeend::ptr&, const block::ptr&) +{ + emit_opcode(opcode::OP_waittillFrameEnd); +} + +void compiler::emit_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk, bool last) +{ + auto end_loc = create_label(); + + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, end_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, end_loc); + } + + blk->transfer(stmt->blk); + + emit_stmt(stmt->stmt, stmt->blk, last); + + last ? emit_opcode(opcode::OP_End) : emit_remove_local_vars(stmt->blk); + + insert_label(end_loc); +} + +void compiler::emit_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk, bool last) +{ + std::vector childs; + auto else_loc = create_label(); + auto end_loc = create_label(); + + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, else_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, else_loc); + } + + blk->transfer(stmt->blk_if); + + emit_stmt(stmt->stmt_if, stmt->blk_if, last); + + emit_remove_local_vars(stmt->blk_if); + + if (stmt->blk_if->abort == abort_t::abort_none) + childs.push_back(stmt->blk_if.get()); + + last ? emit_opcode(opcode::OP_End) : emit_opcode(opcode::OP_jump, end_loc); + + insert_label(else_loc); + + blk->transfer(stmt->blk_else); + + emit_stmt(stmt->stmt_else, stmt->blk_else, last); + + last ? emit_opcode(opcode::OP_End) : emit_remove_local_vars(stmt->blk_else); + + if (stmt->blk_else->abort == abort_t::abort_none) + childs.push_back(stmt->blk_else.get()); + + insert_label(end_loc); + + blk->init_from_child(childs); +} + +void compiler::emit_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = true; + can_continue_ = true; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + blk->transfer(stmt->blk); + stmt->blk->loc_break = break_loc; + stmt->blk->loc_continue = continue_loc; + + emit_create_local_vars(stmt->blk); + + blk->local_vars_create_count = stmt->blk->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + auto begin_loc = insert_label(); + + bool const_cond = is_constant_condition(stmt->test); + + if (!const_cond) + { + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, break_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + } + } + + emit_stmt(stmt->stmt, stmt->blk, false); + + insert_label(continue_loc); + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if (const_cond) + blk->init_from_child(break_blks_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = true; + can_continue_ = true; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + blk->transfer(stmt->blk); + stmt->blk->loc_break = break_loc; + stmt->blk->loc_continue = continue_loc; + + emit_create_local_vars(stmt->blk); + + blk->local_vars_create_count = stmt->blk->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + auto begin_loc = insert_label(); + + emit_stmt(stmt->stmt, stmt->blk, false); + + insert_label(continue_loc); + + bool const_cond = is_constant_condition(stmt->test); + + if (!const_cond) + { + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, break_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + } + } + + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if (const_cond) + blk->init_from_child(break_blks_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = false; + can_continue_ = false; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + emit_stmt(stmt->init, blk, false); + + blk->transfer(stmt->blk); + stmt->blk->loc_break = break_loc; + stmt->blk->loc_continue = continue_loc; + + emit_create_local_vars(stmt->blk); + + blk->local_vars_create_count = stmt->blk->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + blk->transfer(stmt->blk_iter); + + auto begin_loc = insert_label(); + + bool const_cond = is_constant_condition(stmt->test); + + if (!const_cond) + { + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, break_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + } + } + + can_break_ = true; + can_continue_ = true; + + emit_stmt(stmt->stmt, stmt->blk, false); + + if (stmt->blk->abort == abort_t::abort_none) + continue_blks_.push_back(stmt->blk.get()); + + can_break_ = false; + can_continue_ = false; + + insert_label(continue_loc); + + stmt->blk_iter->init_from_child(continue_blks_); + + emit_stmt(stmt->iter, stmt->blk_iter, false); + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if (const_cond) + blk->init_from_child(break_blks_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = false; + can_continue_ = false; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + emit_expr(stmt->array_expr, blk); + emit_expr_variable_ref(stmt->array, blk, true); + emit_expr_variable(stmt->array, blk); + emit_opcode(opcode::OP_CallBuiltin1, "getfirstarraykey"); + emit_expr_variable_ref(stmt->key_expr, blk, true); + + blk->transfer(stmt->ctx); + stmt->ctx->loc_break = break_loc; + stmt->ctx->loc_continue = continue_loc; + + emit_create_local_vars(stmt->ctx); + + blk->local_vars_create_count = stmt->ctx->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + blk->transfer(stmt->ctx_post); + + auto begin_loc = insert_label(); + + emit_expr_variable(stmt->key_expr, blk); + emit_opcode(opcode::OP_CallBuiltin1, "isdefined"); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + + can_break_ = true; + can_continue_ = true; + + emit_expr_variable(stmt->key_expr, stmt->ctx); + emit_opcode(opcode::OP_EvalLocalArrayCached, variable_access_index(stmt->array.as_identifier, stmt->ctx)); + emit_expr_variable_ref(stmt->value_expr, stmt->ctx, true); + emit_stmt(stmt->stmt, stmt->ctx, false); + + if (stmt->ctx->abort == abort_t::abort_none) + continue_blks_.push_back(stmt->ctx.get()); + + can_break_ = false; + can_continue_ = false; + + insert_label(continue_loc); + + stmt->ctx_post->init_from_child(continue_blks_); + + emit_expr_variable(stmt->key_expr, stmt->ctx_post); + emit_expr_variable(stmt->array, stmt->ctx_post); + emit_opcode(opcode::OP_CallBuiltin2, "getnextarraykey"); + emit_expr_variable_ref(stmt->key_expr, stmt->ctx_post, true); + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + emit_expr_clear_local(stmt->array.as_identifier, blk); + if (!stmt->use_key) emit_expr_clear_local(stmt->key_expr.as_identifier, blk); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_break = can_break_; + break_blks_.clear(); + can_break_ = false; + + auto jmptable_loc = create_label(); + auto break_loc = create_label(); + + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_switch, jmptable_loc); + + can_break_ = true; + + std::vector data; + data.push_back(utils::string::va("%d", stmt->stmt->list.size())); + + bool has_default = false; + block* default_ctx = nullptr; + + for (auto i = 0u; i < stmt->stmt->list.size(); i++) + { + auto& entry = stmt->stmt->list[i]; + + if (entry == ast::kind::stmt_case) + { + if (has_default) + { + comp_error(stmt->loc(), "default must be last case"); + } + + auto& case_ = entry.as_case; + if (case_->label == ast::kind::expr_integer) + { + auto loc = insert_label(); + data.push_back("case"); + data.push_back(case_->label.as_integer->value); + data.push_back(loc); + } + else if (case_->label == ast::kind::expr_string) + { + auto loc = insert_label(); + data.push_back("case"); + data.push_back(case_->label.as_string->value); + data.push_back(loc); + } + else + { + throw comp_error(stmt->loc(), "case type must be int or string"); + } + + blk->transfer(case_->blk); + case_->blk->loc_break = break_loc; + emit_stmt_list(case_->stmt, case_->blk, false); + if (case_->stmt->list.size() > 0) + emit_remove_local_vars(case_->blk); + } + else if (entry == ast::kind::stmt_default) + { + auto loc = insert_label(); + data.push_back("default"); + data.push_back(loc); + + has_default = true; + default_ctx = entry.as_default->blk.get(); + + blk->transfer(entry.as_default->blk); + entry.as_default->blk->loc_break = break_loc; + emit_stmt_list(entry.as_default->stmt, entry.as_default->blk, false); + if (entry.as_default->stmt->list.size() > 0) + emit_remove_local_vars(entry.as_default->blk); + } + else + { + throw comp_error(entry.loc(), "missing case statement"); + } + } + + if (has_default) + { + if (default_ctx->abort == abort_t::abort_none) + { + break_blks_.push_back(default_ctx); + } + blk->init_from_child(break_blks_); + } + + insert_label(jmptable_loc); + + emit_opcode(opcode::OP_endswitch, data); + + auto offset = static_cast(7 * stmt->stmt->list.size()); + function_->instructions.back()->size += offset; + index_ += offset; + + insert_label(break_loc); + + can_break_ = old_break; + break_blks_ = old_breaks; +} + +void compiler::emit_stmt_case(const ast::stmt_case::ptr& stmt, const block::ptr&) +{ + throw comp_error(stmt->loc(), "illegal case statement"); +} + +void compiler::emit_stmt_default(const ast::stmt_default::ptr& stmt, const block::ptr&) +{ + throw comp_error(stmt->loc(), "illegal default statement"); +} + +void compiler::emit_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk) +{ + if (!can_break_ || blk->abort != abort_t::abort_none || blk->loc_break == "") + throw comp_error(stmt->loc(), "illegal break statement"); + + break_blks_.push_back(blk.get()); + emit_remove_local_vars(blk); + blk->abort = abort_t::abort_break; + emit_opcode(opcode::OP_jump, blk->loc_break); +} + +void compiler::emit_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk) +{ + if (!can_continue_ || blk->abort != abort_t::abort_none || blk->loc_continue == "") + throw comp_error(stmt->loc(), "illegal continue statement"); + + continue_blks_.push_back(blk.get()); + emit_remove_local_vars(blk); + blk->abort = abort_t::abort_continue; + emit_opcode(opcode::OP_jump, blk->loc_continue); +} + +void compiler::emit_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + blk->abort = abort_t::abort_return; + + if (stmt->expr != ast::kind::null) + { + emit_expr(stmt->expr, blk); + emit_opcode(opcode::OP_Return); + } + else + emit_opcode(opcode::OP_End); +} + +void compiler::emit_stmt_breakpoint(const ast::stmt_breakpoint::ptr&, const block::ptr&) +{ + // TODO: +} + +void compiler::emit_stmt_prof_begin(const ast::stmt_prof_begin::ptr&, const block::ptr&) +{ + // TODO: +} + +void compiler::emit_stmt_prof_end(const ast::stmt_prof_end::ptr&, const block::ptr&) +{ + // TODO: +} + +void compiler::emit_expr(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_paren: + emit_expr(expr.as_paren->child, blk); + break; + case ast::kind::expr_ternary: + emit_expr_ternary(expr.as_ternary, blk); + break; + case ast::kind::expr_and: + emit_expr_and(expr.as_and, blk); + break; + case ast::kind::expr_or: + emit_expr_or(expr.as_or, blk); + break; + case ast::kind::expr_equality: + case ast::kind::expr_inequality: + case ast::kind::expr_less: + case ast::kind::expr_greater: + case ast::kind::expr_less_equal: + case ast::kind::expr_greater_equal: + case ast::kind::expr_bitwise_or: + case ast::kind::expr_bitwise_and: + case ast::kind::expr_bitwise_exor: + case ast::kind::expr_shift_left: + case ast::kind::expr_shift_right: + case ast::kind::expr_add: + case ast::kind::expr_sub: + case ast::kind::expr_mul: + case ast::kind::expr_div: + case ast::kind::expr_mod: + emit_expr_binary(expr.as_binary, blk); + break; + case ast::kind::expr_complement: + emit_expr_complement(expr.as_complement, blk); + break; + case ast::kind::expr_negate: + emit_expr_negate(expr.as_negate, blk); + break; + case ast::kind::expr_not: + emit_expr_not(expr.as_not, blk); + break; + case ast::kind::expr_call: + emit_expr_call(expr.as_call, blk, false); + break; + case ast::kind::expr_method: + emit_expr_method(expr.as_method, blk, false); + break; + case ast::kind::expr_reference: + emit_expr_reference(expr.as_reference, blk); + break; + case ast::kind::expr_add_array: + emit_expr_add_array(expr.as_add_array, blk); + break; + case ast::kind::expr_array: + emit_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + emit_expr_field(expr.as_field, blk); + break; + case ast::kind::expr_size: + emit_expr_size(expr.as_size, blk); + break; + case ast::kind::expr_thisthread: + emit_opcode(opcode::OP_GetThisthread); + break; + case ast::kind::expr_empty_array: + emit_opcode(opcode::OP_EmptyArray); + break; + case ast::kind::expr_undefined: + emit_opcode(opcode::OP_GetUndefined); + break; + case ast::kind::expr_game: + emit_opcode(opcode::OP_GetGame); + break; + case ast::kind::expr_self: + emit_opcode(opcode::OP_GetSelf); + break; + case ast::kind::expr_anim: + emit_opcode(opcode::OP_GetAnim); + break; + case ast::kind::expr_level: + emit_opcode(opcode::OP_GetLevel); + break; + case ast::kind::expr_animation: + emit_expr_animation(expr.as_animation); + break; + case ast::kind::expr_animtree: + emit_expr_animtree(expr.as_animtree); + break; + case ast::kind::expr_identifier: + emit_expr_local(expr.as_identifier, blk); + break; + case ast::kind::expr_istring: + emit_expr_istring(expr.as_istring); + break; + case ast::kind::expr_string: + emit_expr_string(expr.as_string); + break; + case ast::kind::expr_vector: + emit_expr_vector(expr.as_vector, blk); + break; + case ast::kind::expr_float: + emit_expr_float(expr.as_float); + break; + case ast::kind::expr_integer: + emit_expr_integer(expr.as_integer); + break; + case ast::kind::expr_false: + emit_expr_false(expr.as_false); + break; + case ast::kind::expr_true: + emit_expr_true(expr.as_true); + break; + case ast::kind::null: + break; + default: + throw comp_error(expr.loc(), "unknown expression"); + } +} + +void compiler::emit_expr_assign(const ast::expr_assign::ptr& expr, const block::ptr& blk) +{ + if (expr->kind() == ast::kind::expr_assign_equal) + { + if (expr->rvalue == ast::kind::expr_undefined) + { + emit_expr_clear(expr->lvalue, blk); + } + else if (expr->lvalue == ast::kind::expr_tuple) + { + emit_expr(expr->rvalue, blk); + emit_expr_tuple(expr->lvalue.as_tuple, blk); + } + else + { + emit_expr(expr->rvalue, blk); + emit_expr_variable_ref(expr->lvalue, blk, true); + } + + return; + } + + emit_expr(expr->lvalue, blk); + emit_expr(expr->rvalue, blk); + + switch (expr->kind()) + { + case ast::kind::expr_assign_add: + emit_opcode(opcode::OP_plus); + break; + case ast::kind::expr_assign_sub: + emit_opcode(opcode::OP_minus); + break; + case ast::kind::expr_assign_mul: + emit_opcode(opcode::OP_multiply); + break; + case ast::kind::expr_assign_div: + emit_opcode(opcode::OP_divide); + break; + case ast::kind::expr_assign_mod: + emit_opcode(opcode::OP_mod); + break; + case ast::kind::expr_assign_shift_left: + emit_opcode(opcode::OP_shift_left); + break; + case ast::kind::expr_assign_shift_right: + emit_opcode(opcode::OP_shift_right); + break; + case ast::kind::expr_assign_bitwise_or: + emit_opcode(opcode::OP_bit_or); + break; + case ast::kind::expr_assign_bitwise_and: + emit_opcode(opcode::OP_bit_and); + break; + case ast::kind::expr_assign_bitwise_exor: + emit_opcode(opcode::OP_bit_ex_or); + break; + default: + throw comp_error(expr->loc(), "unknown assign operation"); + } + + emit_expr_variable_ref(expr->lvalue, blk, true); +} + +void compiler::emit_expr_clear(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_array: + emit_expr(expr.as_array->key, blk); + expr.as_array->obj == ast::kind::expr_game ? emit_opcode(opcode::OP_GetGameRef) : emit_expr_variable_ref(expr.as_array->obj, blk, false); + emit_opcode(opcode::OP_ClearArray); + break; + case ast::kind::expr_field: + emit_expr_object(expr.as_field->obj, blk); + emit_opcode(opcode::OP_ClearFieldVariable, expr.as_field->field->value); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_GetUndefined); + emit_expr_local_ref(expr.as_identifier, blk, true); + break; + default: + throw comp_error(expr.loc(), "unknown clear variable lvalue"); + } +} + +void compiler::emit_expr_clear_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk) +{ + auto index = variable_stack_index(expr, blk); + + if (index == 0) + emit_opcode(opcode::OP_ClearLocalVariableFieldCached0); + else + emit_opcode(opcode::OP_ClearLocalVariableFieldCached, variable_access_index(expr, blk)); +} + +void compiler::emit_expr_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (is_stmt) + { + emit_expr_variable_ref(expr->lvalue, blk, false); + emit_opcode(opcode::OP_inc); + emit_opcode(opcode::OP_SetVariableField); + } + else + { + // TODO: + } +} + +void compiler::emit_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (is_stmt) + { + emit_expr_variable_ref(expr->lvalue, blk, false); + emit_opcode(opcode::OP_dec); + emit_opcode(opcode::OP_SetVariableField); + } + else + { + // TODO: + } +} + +void compiler::emit_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk) +{ + auto else_loc = create_label(); + auto end_loc = create_label(); + + if (expr->test == ast::kind::expr_not) + { + emit_expr(expr->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, else_loc); + } + else + { + emit_expr(expr->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, else_loc); + } + + emit_expr(expr->true_expr, blk); + emit_opcode(opcode::OP_jump, end_loc); + + insert_label(else_loc); + emit_expr(expr->false_expr, blk); + insert_label(end_loc); +} + +void compiler::emit_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->lvalue, blk); + emit_expr(expr->rvalue, blk); + + switch (expr->kind()) + { + case ast::kind::expr_equality: + emit_opcode(opcode::OP_equality); + break; + case ast::kind::expr_inequality: + emit_opcode(opcode::OP_inequality); + break; + case ast::kind::expr_less: + emit_opcode(opcode::OP_less); + break; + case ast::kind::expr_greater: + emit_opcode(opcode::OP_greater); + break; + case ast::kind::expr_less_equal: + emit_opcode(opcode::OP_less_equal); + break; + case ast::kind::expr_greater_equal: + emit_opcode(opcode::OP_greater_equal); + break; + case ast::kind::expr_bitwise_or: + emit_opcode(opcode::OP_bit_or); + break; + case ast::kind::expr_bitwise_and: + emit_opcode(opcode::OP_bit_and); + break; + case ast::kind::expr_bitwise_exor: + emit_opcode(opcode::OP_bit_ex_or); + break; + case ast::kind::expr_shift_left: + emit_opcode(opcode::OP_shift_left); + break; + case ast::kind::expr_shift_right: + emit_opcode(opcode::OP_shift_right); + break; + case ast::kind::expr_add: + emit_opcode(opcode::OP_plus); + break; + case ast::kind::expr_sub: + emit_opcode(opcode::OP_minus); + break; + case ast::kind::expr_mul: + emit_opcode(opcode::OP_multiply); + break; + case ast::kind::expr_div: + emit_opcode(opcode::OP_divide); + break; + case ast::kind::expr_mod: + emit_opcode(opcode::OP_mod); + break; + default: + throw comp_error(expr->loc(), "unknown binary expression"); + } +} + +void compiler::emit_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk) +{ + auto label = create_label(); + + emit_expr(expr->lvalue, blk); + emit_opcode(opcode::OP_JumpOnFalseExpr, label); + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_CastBool); + + insert_label(label); +} + +void compiler::emit_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk) +{ + auto label = create_label(); + + emit_expr(expr->lvalue, blk); + emit_opcode(opcode::OP_JumpOnTrueExpr, label); + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_CastBool); + + insert_label(label); +} + +void compiler::emit_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_BoolComplement); +} + +void compiler::emit_expr_negate(const ast::expr_negate::ptr& expr, const block::ptr& blk) +{ + emit_opcode(opcode::OP_GetZero); + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_minus); +} + +void compiler::emit_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_BoolNot); +} + +void compiler::emit_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (expr->call == ast::kind::expr_pointer) + emit_expr_call_pointer(expr->call.as_pointer, blk, is_stmt); + else if (expr->call == ast::kind::expr_function) + emit_expr_call_function(expr->call.as_function, blk, is_stmt); + else + throw comp_error(expr->loc(), "unknown function call expression"); +} + +void compiler::emit_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (expr->mode == ast::call::mode::normal) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + emit_expr(expr->func, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptFunctionCallPointer); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptThreadCallPointer, argcount); + break; + case ast::call::mode::childthread: + throw comp_error(expr->loc(), "childthread unimplemented!!"); +// emit_opcode(opcode::OP_ScriptChildThreadCallPointer, argcount); + break; + case ast::call::mode::builtin: + emit_opcode(opcode::OP_CallBuiltinPointer, argcount); + break; + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (is_stmt && mode_ == gsc::build::prod) + { + const auto& name = expr->name->value; + if (name == "assert" || name == "assertex" || name == "assertmsg") return; + } + + auto type = resolve_function_type(expr); + + if (type != ast::call::type::builtin && expr->mode == ast::call::mode::normal && expr->args->list.size() > 0) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + if (type == ast::call::type::local) + { + switch (expr->mode) + { + case ast::call::mode::normal: + if (expr->args->list.size() > 0) + emit_opcode(opcode::OP_ScriptLocalFunctionCall, expr->name->value); + else + emit_opcode(opcode::OP_ScriptLocalFunctionCall2, expr->name->value); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptLocalThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptLocalChildThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no local builtins + break; + } + } + else if (type == ast::call::type::far) + { + switch (expr->mode) + { + case ast::call::mode::normal: + if (expr->args->list.size() > 0) + emit_opcode(opcode::OP_ScriptFarFunctionCall, { expr->path->value, expr->name->value }); + else + emit_opcode(opcode::OP_ScriptFarFunctionCall2, { expr->path->value, expr->name->value }); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptFarThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptFarChildThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no far builtins + break; + } + } + else if (type == ast::call::type::builtin) + { + if (expr->mode != ast::call::mode::normal) + throw comp_error(expr->loc(), "builtin calls can't be threaded"); + + switch (expr->args->list.size()) + { + case 0: + emit_opcode(opcode::OP_CallBuiltin0, expr->name->value); + break; + case 1: + emit_opcode(opcode::OP_CallBuiltin1, expr->name->value); + break; + case 2: + emit_opcode(opcode::OP_CallBuiltin2, expr->name->value); + break; + case 3: + emit_opcode(opcode::OP_CallBuiltin3, expr->name->value); + break; + case 4: + emit_opcode(opcode::OP_CallBuiltin4, expr->name->value); + break; + case 5: + emit_opcode(opcode::OP_CallBuiltin5, expr->name->value); + break; + default: + emit_opcode(opcode::OP_CallBuiltin, { expr->name->value, argcount }); + break; + } + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (expr->call == ast::kind::expr_pointer) + emit_expr_method_pointer(expr->call.as_pointer, expr->obj, blk, is_stmt); + else if (expr->call == ast::kind::expr_function) + emit_expr_method_function(expr->call.as_function, expr->obj, blk, is_stmt); + else + throw comp_error(expr->loc(), "unknown method call expression"); +} + +void compiler::emit_expr_method_pointer(const ast::expr_pointer::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt) +{ + if (expr->mode == ast::call::mode::normal) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + emit_expr(obj, blk); + emit_expr(expr->func, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptMethodCallPointer); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptMethodThreadCallPointer, argcount); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptMethodChildThreadCallPointer, argcount); + break; + case ast::call::mode::builtin: + emit_opcode(opcode::OP_CallBuiltinMethodPointer, argcount); + break; + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_method_function(const ast::expr_function::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt) +{ + auto type = resolve_function_type(expr); + + if (type != ast::call::type::builtin && expr->mode == ast::call::mode::normal) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + emit_expr(obj, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + if (type == ast::call::type::local) + { + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptLocalMethodCall, expr->name->value); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptLocalMethodThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptLocalMethodChildThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no local builtins + break; + } + } + else if (type == ast::call::type::far) + { + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptFarMethodCall, { expr->path->value, expr->name->value }); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptFarMethodThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptFarMethodChildThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no far builtins + break; + } + } + else if (type == ast::call::type::builtin) + { + if (expr->mode != ast::call::mode::normal) + throw comp_error(expr->loc(), "builtin calls can't be threaded"); + + switch (expr->args->list.size()) + { + case 0: + emit_opcode(opcode::OP_CallBuiltinMethod0, expr->name->value); + break; + case 1: + emit_opcode(opcode::OP_CallBuiltinMethod1, expr->name->value); + break; + case 2: + emit_opcode(opcode::OP_CallBuiltinMethod2, expr->name->value); + break; + case 3: + emit_opcode(opcode::OP_CallBuiltinMethod3, expr->name->value); + break; + case 4: + emit_opcode(opcode::OP_CallBuiltinMethod4, expr->name->value); + break; + case 5: + emit_opcode(opcode::OP_CallBuiltinMethod5, expr->name->value); + break; + default: + emit_opcode(opcode::OP_CallBuiltinMethod, { expr->name->value, argcount }); + break; + } + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk) +{ + emit_opcode(opcode::OP_EmptyArray); + + for (const auto& arg : expr->args->list) + { + emit_expr(arg, blk); + emit_opcode(opcode::OP_AddArray); + } +} + +void compiler::emit_expr_parameters(const ast::expr_parameters::ptr& expr, const block::ptr& blk) +{ + for (const auto& entry : expr->list) + { + variable_initialize(entry, blk); + emit_opcode(opcode::OP_SafeCreateVariableFieldCached, variable_create_index(entry, blk)); + } + + emit_opcode(opcode::OP_checkclearparams); +} + +void compiler::emit_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk) +{ + std::reverse(expr->list.begin(), expr->list.end()); + + for (auto& entry : expr->list) + { + emit_expr(entry, blk); + } +} + +void compiler::emit_expr_reference(const ast::expr_reference::ptr& expr, const block::ptr&) +{ + bool method = false; + auto type = resolve_reference_type(expr, method); + + switch (type) + { + case ast::call::type::local: + emit_opcode(opcode::OP_GetLocalFunction, expr->name->value); + break; + case ast::call::type::far: + emit_opcode(opcode::OP_GetFarFunction, { expr->path->value, expr->name->value }); + break; + case ast::call::type::builtin: + if (method) + emit_opcode(opcode::OP_GetBuiltinMethod, expr->name->value); + else + emit_opcode(opcode::OP_GetBuiltinFunction, expr->name->value); + break; + } +} + +void compiler::emit_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->obj, blk); + emit_opcode(opcode::OP_size); +} + +void compiler::emit_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + emit_expr_variable_ref(expr->temp, blk, true); + + auto index = 0; + + for (const auto& entry : expr->list) + { + if (index == 0) + emit_opcode(opcode::OP_GetZero); + else + emit_opcode(opcode::OP_GetByte, utils::string::va("%d", index)); + + index++; + + emit_opcode(opcode::OP_EvalLocalArrayCached, variable_access_index(expr->temp.as_identifier, blk)); + + emit_expr_variable_ref(entry, blk, true); + } + + emit_expr_clear_local(expr->temp.as_identifier, blk); +} + +void compiler::emit_expr_variable_ref(const ast::expr& expr, const block::ptr& blk, bool set) +{ + switch (expr.kind()) + { + case ast::kind::expr_array: + emit_expr_array_ref(expr.as_array, blk, set); + break; + case ast::kind::expr_field: + emit_expr_field_ref(expr.as_field, blk, set); + break; + case ast::kind::expr_identifier: + emit_expr_local_ref(expr.as_identifier, blk, set); + break; + default: + throw comp_error(expr.loc(), "invalid lvalue"); + } +} + +void compiler::emit_expr_array_ref(const ast::expr_array::ptr& expr, const block::ptr& blk, bool set) +{ + emit_expr(expr->key, blk); + + switch (expr->obj.kind()) + { + case ast::kind::expr_game: + emit_opcode(opcode::OP_GetGameRef); + emit_opcode(opcode::OP_EvalArrayRef); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_array: + case ast::kind::expr_field: + emit_expr_variable_ref(expr->obj, blk, false); + emit_opcode(opcode::OP_EvalArrayRef); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_identifier: + { + if (!variable_initialized(expr->obj.as_identifier, blk)) + { + variable_initialize(expr->obj.as_identifier, blk); + emit_opcode(opcode::OP_EvalNewLocalArrayRefCached0, variable_create_index(expr->obj.as_identifier, blk)); + + if (!set) throw comp_error(expr->loc(), "INTERNAL: VAR CREATED BUT NOT SET!"); + } + else if (variable_stack_index(expr->obj.as_identifier, blk) == 0) + { + emit_opcode(opcode::OP_EvalLocalArrayRefCached0); + } + else + { + emit_opcode(opcode::OP_EvalLocalArrayRefCached, variable_access_index(expr->obj.as_identifier, blk)); + } + + if (set) emit_opcode(opcode::OP_SetVariableField); + } + break; + case ast::kind::expr_call: + case ast::kind::expr_method: + default: + throw comp_error(expr->loc(), "invalid array lvalue"); + } +} + +void compiler::emit_expr_field_ref(const ast::expr_field::ptr& expr, const block::ptr& blk, bool set) +{ + const auto& field = expr->field->value; + + switch (expr->obj.kind()) + { + case ast::kind::expr_level: + set ? emit_opcode(opcode::OP_SetLevelFieldVariableField, field) : emit_opcode(opcode::OP_EvalLevelFieldVariableRef, field); + break; + case ast::kind::expr_anim: + set ? emit_opcode(opcode::OP_SetAnimFieldVariableField, field) : emit_opcode(opcode::OP_EvalAnimFieldVariableRef, field); + break; + case ast::kind::expr_self: + set ? emit_opcode(opcode::OP_SetSelfFieldVariableField, field) : emit_opcode(opcode::OP_EvalSelfFieldVariableRef, field); + break; + case ast::kind::expr_array: + emit_expr_array(expr->obj.as_array, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_field: + emit_expr_field(expr->obj.as_field, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_EvalLocalVariableObjectCached, variable_access_index(expr->obj.as_identifier, blk)); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_call: + emit_expr_call(expr->obj.as_call, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_method: + emit_expr_method(expr->obj.as_method, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + default: + throw comp_error(expr->obj.loc(), "not an object"); + } +} + +void compiler::emit_expr_local_ref(const ast::expr_identifier::ptr& expr, const block::ptr& blk, bool set) +{ + const auto itr = constants_.find(expr->value); + + if (itr != constants_.end()) + { + throw comp_error(expr->loc(), "variable name already defined as constant '" + expr->value + "'"); + } + + if (set) + { + if (!variable_initialized(expr, blk)) + { + variable_initialize(expr, blk); + emit_opcode(opcode::OP_SetNewLocalVariableFieldCached0, variable_create_index(expr, blk)); + } + else if (variable_stack_index(expr, blk) == 0) + { + emit_opcode(opcode::OP_SetLocalVariableFieldCached0); + } + else + { + emit_opcode(opcode::OP_SetLocalVariableFieldCached, variable_access_index(expr, blk)); + } + } + else + { + auto index = variable_stack_index(expr, blk); + + if (index == 0) + emit_opcode(opcode::OP_EvalLocalVariableRefCached0); + else + emit_opcode(opcode::OP_EvalLocalVariableRefCached, variable_access_index(expr, blk)); + } +} + +void compiler::emit_expr_variable(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_array: + emit_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + emit_expr_field(expr.as_field, blk); + break; + case ast::kind::expr_identifier: + emit_expr_local(expr.as_identifier, blk); + break; + default: + throw comp_error(expr.loc(), "invalid variable type."); + } +} + +void compiler::emit_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->key, blk); + + if (expr->obj == ast::kind::expr_identifier) + { + emit_opcode(opcode::OP_EvalLocalArrayCached, variable_access_index(expr->obj.as_identifier, blk)); + } + else + { + emit_expr(expr->obj, blk); + emit_opcode(opcode::OP_EvalArray); + } +} + +void compiler::emit_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) +{ + const auto& field = expr->field->value; + + switch (expr->obj.kind()) + { + case ast::kind::expr_level: + emit_opcode(opcode::OP_EvalLevelFieldVariable, field); + break; + case ast::kind::expr_anim: + emit_opcode(opcode::OP_EvalAnimFieldVariable, field); + break; + case ast::kind::expr_self: + emit_opcode(opcode::OP_EvalSelfFieldVariable, field); + break; + case ast::kind::expr_array: + emit_expr_array(expr->obj.as_array, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_field: + emit_expr_field(expr->obj.as_field, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_call: + emit_expr_call(expr->obj.as_call, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_method: + emit_expr_method(expr->obj.as_method, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_EvalLocalVariableObjectCached, variable_access_index(expr->obj.as_identifier, blk)); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + default: + throw comp_error(expr->loc(), "unknown field variable object type"); + } +} + +void compiler::emit_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk) +{ + // is constant ( should only allow: string, loc string, number, vector) + const auto itr = constants_.find(expr->value); + + if (itr != constants_.end()) + { + emit_expr(itr->second, blk); + return; + } + + // is local var + auto index = variable_stack_index(expr, blk); + + switch (index) + { + case 0: + emit_opcode(opcode::OP_EvalLocalVariableCached0); + break; + case 1: + emit_opcode(opcode::OP_EvalLocalVariableCached1); + break; + case 2: + emit_opcode(opcode::OP_EvalLocalVariableCached2); + break; + case 3: + emit_opcode(opcode::OP_EvalLocalVariableCached3); + break; + case 4: + emit_opcode(opcode::OP_EvalLocalVariableCached4); + break; + case 5: + emit_opcode(opcode::OP_EvalLocalVariableCached5); + break; + default: + emit_opcode(opcode::OP_EvalLocalVariableCached, variable_access_index(expr, blk)); + break; + } +} + +void compiler::emit_expr_object(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_level: + emit_opcode(opcode::OP_GetLevelObject); + break; + case ast::kind::expr_anim: + emit_opcode(opcode::OP_GetAnimObject); + break; + case ast::kind::expr_self: + emit_opcode(opcode::OP_GetSelfObject); + break; + case ast::kind::expr_array: + emit_expr_array(expr.as_array, blk); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_field: + emit_expr_field(expr.as_field, blk); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_call: + emit_expr_call(expr.as_call, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_method: + emit_expr_method(expr.as_method, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_EvalLocalVariableObjectCached, variable_access_index(expr.as_identifier, blk)); + break; + default: + throw comp_error(expr.loc(), "not an object"); + } +} + +void compiler::emit_expr_vector(const ast::expr_vector::ptr& expr, const block::ptr& blk) +{ + std::vector data; + + bool isexpr = false; + + if (expr->x == ast::kind::expr_integer) + data.push_back(expr->x.as_integer->value); + else if (expr->x == ast::kind::expr_float) + data.push_back(expr->x.as_float->value); + else isexpr = true; + + if (expr->y == ast::kind::expr_integer) + data.push_back(expr->y.as_integer->value); + else if (expr->y == ast::kind::expr_float) + data.push_back(expr->y.as_float->value); + else isexpr = true; + + if (expr->z == ast::kind::expr_integer) + data.push_back(expr->z.as_integer->value); + else if (expr->z == ast::kind::expr_float) + data.push_back(expr->z.as_float->value); + else isexpr = true; + + if (!isexpr) + { + auto base = index_ + 1; + auto algn = (base + (4 - 1)) & ~(4 - 1); + emit_opcode(opcode::OP_GetVector, data); + index_ += (algn - base); + } + else + { + emit_expr(expr->z, blk); + emit_expr(expr->y, blk); + emit_expr(expr->x, blk); + emit_opcode(opcode::OP_vector); + } +} + +void compiler::emit_expr_animation(const ast::expr_animation::ptr& expr) +{ + if (animtrees_.size() == 0) + { + throw comp_error(expr->loc(), "trying to use animation without specified using animtree"); + } + + auto& tree = animtrees_.back(); + + if (tree.loaded) + { + emit_opcode(opcode::OP_GetAnimation, { "''", expr->value }); + } + else + { + emit_opcode(opcode::OP_GetAnimation, { tree.name, expr->value }); + tree.loaded = true; + } +} + +void compiler::emit_expr_animtree(const ast::expr_animtree::ptr& expr) +{ + if (animtrees_.size() == 0) + { + throw comp_error(expr->loc(), "trying to use animtree without specified using animtree"); + } + + auto& tree = animtrees_.back(); + + if (tree.loaded) + { + emit_opcode(opcode::OP_GetAnimTree, "''"); + } + else + { + emit_opcode(opcode::OP_GetAnimTree, tree.name); + tree.loaded = true; + } +} + +void compiler::emit_expr_istring(const ast::expr_istring::ptr& expr) +{ + emit_opcode(opcode::OP_GetIString, expr->value); +} + +void compiler::emit_expr_string(const ast::expr_string::ptr& expr) +{ + emit_opcode(opcode::OP_GetString, expr->value); +} + +void compiler::emit_expr_float(const ast::expr_float::ptr& expr) +{ + emit_opcode(opcode::OP_GetFloat, expr->value); +} + +void compiler::emit_expr_integer(const ast::expr_integer::ptr& expr) +{ + auto value = std::atoi(expr->value.data()); + + if (value == 0) + { + emit_opcode(opcode::OP_GetZero); + } + else if (value > 0 && value < 256) + { + emit_opcode(opcode::OP_GetByte, expr->value); + } + else if (value < 0 && value > -256) + { + emit_opcode(opcode::OP_GetNegByte, expr->value.substr(1)); + } + else if (value > 0 && value < 65536) + { + emit_opcode(opcode::OP_GetUnsignedShort, expr->value); + } + else if (value < 0 && value > -65536) + { + emit_opcode(opcode::OP_GetNegUnsignedShort, expr->value.substr(1)); + } + else + { + emit_opcode(opcode::OP_GetInteger, expr->value); + } +} + +void compiler::emit_expr_false(const ast::expr_false::ptr&) +{ + emit_opcode(opcode::OP_GetZero); +} + +void compiler::emit_expr_true(const ast::expr_true::ptr&) +{ + emit_opcode(opcode::OP_GetByte, "1"); +} + +void compiler::emit_create_local_vars(const block::ptr& blk) +{ + if (blk->local_vars_create_count != blk->local_vars_public_count) + { + for (auto i = blk->local_vars_create_count; i < blk->local_vars_public_count; i++) + { + auto data = utils::string::va("%d", blk->local_vars.at(i).create); + emit_opcode(opcode::OP_CreateLocalVariable, data); + blk->local_vars.at(i).init = true; + } + blk->local_vars_create_count = blk->local_vars_public_count; + } +} + +void compiler::emit_remove_local_vars(const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + auto count = blk->local_vars_create_count - blk->local_vars_public_count; + + if (count > 0) + { + auto data = utils::string::va("%d", count); + emit_opcode(opcode::OP_RemoveLocalVariables, data); + } + } +} + +void compiler::emit_opcode(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(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(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 ast::decl_thread::ptr& decl, const block::ptr& blk) +{ + process_expr_parameters(decl->params, blk); + process_stmt_list(decl->stmt, blk); +} + +void compiler::process_stmt(const ast::stmt& stmt, const block::ptr& blk) +{ + switch (stmt.kind()) + { + case ast::kind::stmt_list: + process_stmt_list(stmt.as_list, blk); + break; + case ast::kind::stmt_dev: + process_stmt_dev(stmt.as_dev, blk); + break; + case ast::kind::stmt_expr: + process_stmt_expr(stmt.as_expr, blk); + break; + case ast::kind::stmt_assign: + process_stmt_assign(stmt.as_assign, blk); + break; + case ast::kind::stmt_waittill: + process_stmt_waittill(stmt.as_waittill, blk); + break; + case ast::kind::stmt_if: + process_stmt_if(stmt.as_if, blk); + break; + case ast::kind::stmt_ifelse: + process_stmt_ifelse(stmt.as_ifelse, blk); + break; + case ast::kind::stmt_while: + process_stmt_while(stmt.as_while, blk); + break; + case ast::kind::stmt_dowhile: + process_stmt_dowhile(stmt.as_dowhile, blk); + break; + case ast::kind::stmt_for: + process_stmt_for(stmt.as_for, blk); + break; + case ast::kind::stmt_foreach: + process_stmt_foreach(stmt.as_foreach, blk); + break; + case ast::kind::stmt_switch: + process_stmt_switch(stmt.as_switch, blk); + break; + case ast::kind::stmt_break: + process_stmt_break(stmt.as_break, blk); + break; + case ast::kind::stmt_continue: + process_stmt_continue(stmt.as_continue, blk); + break; + case ast::kind::stmt_return: + process_stmt_return(stmt.as_return, blk); + break; + case ast::kind::stmt_call: + case ast::kind::stmt_endon: + case ast::kind::stmt_notify: + case ast::kind::stmt_wait: + case ast::kind::stmt_waittillmatch: + case ast::kind::stmt_waittillframeend: + case ast::kind::stmt_case: + case ast::kind::stmt_default: + case ast::kind::stmt_breakpoint: + case ast::kind::stmt_prof_begin: + case ast::kind::stmt_prof_end: + break; + default: + throw comp_error(stmt.loc(), "unknown statement"); + } +} + +void compiler::process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk) +{ + for (const auto& entry : stmt->list) + { + process_stmt(entry, blk); + } +} + +void compiler::process_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk) +{ + process_stmt_list(stmt->list, blk); +} + +void compiler::process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr(stmt->expr.as_increment->lvalue, blk); + break; + case ast::kind::expr_decrement: + process_expr(stmt->expr.as_decrement->lvalue, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr(stmt->expr.as_assign->lvalue, blk); + break; + case ast::kind::null: + break; + default: + throw comp_error(stmt->loc(), "unknown expr statement expression"); + } +} + +void compiler::process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr(stmt->expr.as_increment->lvalue, blk); + break; + case ast::kind::expr_decrement: + process_expr(stmt->expr.as_decrement->lvalue, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr(stmt->expr.as_assign->lvalue, blk); + break; + default: + throw comp_error(stmt->loc(), "unknown assign statement expression"); + } +} + +void compiler::process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk) +{ + for (const auto& entry : stmt->args->list) + { + if (entry != ast::kind::expr_identifier) + { + throw comp_error(entry.loc(), "illegal waittill param, must be a local variable"); + } + + variable_register(entry.as_identifier->value, blk); + } +} + +void compiler::process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk) +{ + stmt->blk = std::make_unique(); + + blk->copy(stmt->blk); + process_stmt(stmt->stmt, stmt->blk); + + std::vector childs({ stmt->blk.get() }); + blk->merge(childs); +} + +void compiler::process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk) +{ + std::vector childs; + auto abort = abort_t::abort_return; + + stmt->blk_if = std::make_unique(); + stmt->blk_else = std::make_unique(); + + blk->copy(stmt->blk_if); + process_stmt(stmt->stmt_if, stmt->blk_if); + + if (stmt->blk_if->abort <= abort_t::abort_return) + { + abort = stmt->blk_if->abort; + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_if.get()); + } + + blk->copy(stmt->blk_else); + process_stmt(stmt->stmt_else, stmt->blk_else); + + if (stmt->blk_else->abort <= abort) + { + abort = stmt->blk_else->abort; + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_else.get()); + } + + if (blk->abort == abort_t::abort_none) + blk->abort = abort; + + blk->append(childs); + blk->merge(childs); +} + +void compiler::process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk) +{ + bool const_cond = is_constant_condition(stmt->test); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + stmt->blk = std::make_unique(); + + blk->copy(stmt->blk); + process_stmt(stmt->stmt, stmt->blk); + + continue_blks_.push_back(stmt->blk.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + if (const_cond) blk->append(break_blks_); + + blk->merge({ stmt->blk.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk) +{ + bool const_cond = is_constant_condition(stmt->test); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + stmt->blk = std::make_unique(); + + blk->copy(stmt->blk); + process_stmt(stmt->stmt, stmt->blk); + + continue_blks_.push_back(stmt->blk.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + if (const_cond) blk->append(break_blks_); + + blk->merge({ stmt->blk.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk) +{ + bool const_cond = is_constant_condition(stmt->test); + + stmt->blk = std::make_unique(); + stmt->blk_iter = std::make_unique(); + + process_stmt(stmt->init, blk); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + blk->copy(stmt->blk); + blk->copy(stmt->blk_iter); + + process_stmt(stmt->stmt, stmt->blk); + + continue_blks_.push_back(stmt->blk.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + process_stmt(stmt->iter, stmt->blk_iter); + + blk->append({ stmt->blk_iter.get() }); + blk->merge({ stmt->blk_iter.get() }); + + if (const_cond) blk->append(break_blks_); + + blk->merge({ stmt->blk.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk) +{ + auto array_name = utils::string::va("_temp_%d", ++label_idx_); + auto key_name = utils::string::va("_temp_%d", ++label_idx_); + + stmt->array = ast::expr(std::make_unique(stmt->loc(), array_name)); + + if (!stmt->use_key) + stmt->key_expr = ast::expr(std::make_unique(stmt->loc(), key_name)); + + key_name = stmt->key_expr.as_identifier->value; + + // calculate variables + + stmt->ctx = std::make_unique(); + stmt->ctx_post = std::make_unique(); + + // calculate pre_expr variables + process_expr(stmt->array, blk); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + blk->copy(stmt->ctx); + blk->copy(stmt->ctx_post); + + // calculate stmt variables & add missing array access as first stmt + process_expr(stmt->value_expr, stmt->ctx); + process_stmt(stmt->stmt, stmt->ctx); + + continue_blks_.push_back(stmt->ctx.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + process_expr(stmt->key_expr, stmt->ctx_post); + + blk->append({ stmt->ctx_post.get() }); + blk->merge({ stmt->ctx_post.get() }); + blk->merge({ stmt->ctx.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk) +{ + auto stmt_list = std::make_unique(stmt->stmt->loc()); + auto current_case = ast::stmt(nullptr); + + auto num = stmt->stmt->list.size(); + + for (auto i = 0u; i < num; i++) + { + auto& entry = stmt->stmt->list[0]; + + if (entry == ast::kind::stmt_case || entry == ast::kind::stmt_default) + { + if (current_case.as_node != nullptr) + { + stmt_list->list.push_back(std::move(current_case)); + } + + current_case = std::move(stmt->stmt->list[0]); + stmt->stmt->list.erase(stmt->stmt->list.begin()); + } + else + { + if (current_case.as_node != nullptr) + { + if (current_case == ast::kind::stmt_case) + { + current_case.as_case->stmt->list.push_back(std::move(entry)); + stmt->stmt->list.erase(stmt->stmt->list.begin()); + } + else + { + current_case.as_default->stmt->list.push_back(std::move(entry)); + stmt->stmt->list.erase(stmt->stmt->list.begin()); + } + } + else + { + throw comp_error(entry.loc(), "missing case statement"); + } + } + } + + if (current_case.as_node != nullptr) + { + stmt_list->list.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; + block* default_ctx = nullptr; + auto old_breaks = break_blks_; + break_blks_.clear(); + + for (auto i = 0u; i < stmt_list->list.size(); i++) + { + auto& entry = stmt_list->list[i]; + + if (entry == ast::kind::stmt_case) + { + entry.as_case->blk = std::make_unique(); + blk->copy(entry.as_case->blk); + process_stmt_list(entry.as_case->stmt, entry.as_case->blk); + + if (entry.as_case->blk->abort != abort_t::abort_none) + { + if (entry.as_case->blk->abort == abort_t::abort_break ) + { + entry.as_case->blk->abort = abort_t::abort_none; + abort = abort_t::abort_none; + childs.push_back(entry.as_case->blk.get()); + } + else if (entry.as_case->blk->abort <= abort ) + { + abort = entry.as_case->blk->abort; + } + } + } + else if (entry == ast::kind::stmt_default) + { + entry.as_default->blk = std::make_unique(); + blk->copy(entry.as_default->blk); + process_stmt_list(entry.as_default->stmt, entry.as_default->blk); + has_default = true; + default_ctx = entry.as_default->blk.get(); + + if (entry.as_default->blk->abort != abort_t::abort_none) + { + if (entry.as_default->blk->abort == abort_t::abort_break ) + { + entry.as_default->blk->abort = abort_t::abort_none; + abort = abort_t::abort_none; + childs.push_back(entry.as_default->blk.get()); + } + else if (entry.as_default->blk->abort <= abort ) + { + abort = entry.as_default->blk->abort; + } + } + } + } + + stmt->stmt =std::move(stmt_list); + + if (has_default) + { + if (default_ctx->abort == abort_t::abort_none) + { + break_blks_.push_back(default_ctx); + + if (blk->abort == abort_t::abort_none) + blk->abort = abort; + } + + blk->append(break_blks_); + blk->merge(childs); + } + + break_blks_ = old_breaks; +} + +void compiler::process_stmt_break(const ast::stmt_break::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + break_blks_.push_back(blk.get()); + blk->abort = abort_t::abort_break; + } +} + +void compiler::process_stmt_continue(const ast::stmt_continue::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + continue_blks_.push_back(blk.get()); + blk->abort = abort_t::abort_continue; + } +} + +void compiler::process_stmt_return(const ast::stmt_return::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_return; + } +} + +void compiler::process_expr(const ast::expr& expr, const block::ptr& blk) +{ + if (expr == ast::kind::expr_identifier) + { + variable_register(expr.as_identifier->value, blk); + } + else if (expr == ast::kind::expr_array) + { + process_expr(expr.as_array->obj, blk); + } + else if (expr == ast::kind::expr_tuple) + { + process_expr_tuple(expr.as_tuple, blk); + } +} + +void compiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + auto array = utils::string::va("_temp_%d", ++label_idx_); + expr->temp = ast::expr(std::make_unique(expr->loc(), array)); + + process_expr(expr->temp, blk); + + for (const auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void compiler::process_expr_parameters(const ast::expr_parameters::ptr& decl, const block::ptr& blk) +{ + for (const auto& entry : decl->list) + { + variable_register(entry->value, blk); + } +} + +void compiler::variable_register(const std::string& name, const block::ptr& blk) +{ + auto it = std::find_if (blk->local_vars.begin(), blk->local_vars.end(), + [&](const gsc::local_var& v) { return v.name == name; }); + + if (it == blk->local_vars.end()) + { + auto found = false; + for (std::size_t i = 0; i < local_stack_.size(); i++) + { + if (local_stack_[i] == name) + { + blk->local_vars.push_back({ name, static_cast(i), false }); + found = true; + break; + } + } + + if (!found) + { + blk->local_vars.push_back({ name, stack_idx_, false }); + local_stack_.push_back(name); + stack_idx_++; + } + } +} + +void compiler::variable_initialize(const ast::expr_identifier::ptr& name, const block::ptr& blk) +{ + for (std::uint32_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + if (!blk->local_vars[i].init) + { + for (std::uint32_t j = 0; j < i; j++) + { + if (!blk->local_vars[j].init) + { + emit_opcode(opcode::OP_CreateLocalVariable, utils::string::va("%d", blk->local_vars[j].create)); + blk->local_vars[j].init = true; + } + } + blk->local_vars[i].init = true; + blk->local_vars_create_count = i + 1; + return; + } + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +void compiler::variable_create(const ast::expr_identifier::ptr& name, const block::ptr& blk) +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + auto& var = blk->local_vars.at(i); + if (var.name == name->value) + { + if (!var.init) + { + emit_opcode(opcode::OP_CreateLocalVariable, utils::string::va("%d", var.create)); + var.init = true; + blk->local_vars_create_count++; + } + return; + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_stack_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::uint8_t +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + if (blk->local_vars.at(i).init) + { + return static_cast(blk->local_vars_create_count - 1 - i); + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not initialized."); + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_create_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + return utils::string::va("%d", blk->local_vars[i].create); + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_access_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + if (blk->local_vars.at(i).init) + { + return utils::string::va("%d", blk->local_vars_create_count - 1 - i); + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not initialized."); + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_initialized(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> bool +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + return blk->local_vars.at(i).init; + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::resolve_function_type(const ast::expr_function::ptr& expr) -> ast::call::type +{ + if (expr->path->value != "") + return ast::call::type::far; + + auto& name = expr->name->value; + + if (resolver::find_function(name) || resolver::find_method(name)) + return ast::call::type::builtin; + + for (const auto& entry : local_functions_) + { + if (entry == name) + return ast::call::type::local; + } + + for (const auto& inc : includes_) + { + for (const auto& fun : inc.funcs) + { + if (name == fun) + { + expr->path->value = inc.name; + return ast::call::type::far; + } + } + } + + throw comp_error(expr->loc(), "couldn't determine function type"); +} + +auto compiler::resolve_reference_type(const ast::expr_reference::ptr& expr, bool& method) -> ast::call::type +{ + if (expr->path->value != "") + return ast::call::type::far; + + auto& name = expr->name->value; + + if (resolver::find_function(name)) + { + method = false; + return ast::call::type::builtin; + } + + if (resolver::find_method(name)) + { + method = true; + return ast::call::type::builtin; + } + + for (const auto& entry : local_functions_) + { + if (entry == name) + return ast::call::type::local; + } + + for (const auto& inc : includes_) + { + for (const auto& fun : inc.funcs) + { + if (name == fun) + { + expr->path->value = inc.name; + return ast::call::type::far; + } + } + } + + throw comp_error(expr->loc(), "couldn't determine function reference type"); +} + +auto compiler::is_constant_condition(const ast::expr& expr) -> bool +{ + switch (expr.kind()) + { + case ast::kind::null: + case ast::kind::expr_true: + return true; + case ast::kind::expr_false: + throw comp_error(expr.loc(), "condition can't be always false!"); + case ast::kind::expr_integer: + { + auto num = std::stoi(expr.as_integer->value); + if (num != 0) + return true; + else + throw comp_error(expr.loc(), "condition can't be always false!"); + } + default: + break; + } + + return false; +} + +auto compiler::create_label() -> std::string +{ + label_idx_++; + return utils::string::va("loc_%d", label_idx_); +} + +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 (static_cast(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&) -> bool +{ + return false; +} + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/compiler.hpp b/src/experimental/iw6c/xsk/compiler.hpp new file mode 100644 index 00000000..05ecf0a9 --- /dev/null +++ b/src/experimental/iw6c/xsk/compiler.hpp @@ -0,0 +1,159 @@ +// Copyright 2022 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::iw6c +{ + +enum class opcode : std::uint8_t; + +class compiler : public gsc::compiler +{ + build mode_; + std::string filename_; + std::vector assembly_; + 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::vector break_blks_; + std::vector continue_blks_; + bool can_break_; + bool can_continue_; + bool developer_thread_; + +public: + auto output() -> std::vector; + void compile(const std::string& file, std::vector& data); + void mode(build mode); + +private: + auto parse_buffer(const std::string& file, const char* data, size_t size) -> ast::program::ptr; + auto parse_file(const std::string& file) -> ast::program::ptr; + void compile_program(const ast::program::ptr& program); + void emit_include(const ast::include::ptr& include); + void emit_declaration(const ast::decl& decl); + void emit_decl_usingtree(const ast::decl_usingtree::ptr& animtree); + void emit_decl_constant(const ast::decl_constant::ptr& constant); + void emit_decl_thread(const ast::decl_thread::ptr& thread); + void emit_stmt(const ast::stmt& stmt, const block::ptr& blk, bool last); + void emit_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk); + void emit_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk); + void emit_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk); + void emit_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk); + void emit_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk); + void emit_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk); + void emit_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk); + void emit_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk); + void emit_stmt_waittillframeend(const ast::stmt_waittillframeend::ptr& stmt, const block::ptr& blk); + void emit_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk); + void emit_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk); + void emit_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk); + void emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk); + void emit_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk); + void emit_stmt_case(const ast::stmt_case::ptr& stmt, const block::ptr& blk); + void emit_stmt_default(const ast::stmt_default::ptr& stmt, const block::ptr& blk); + void emit_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk); + void emit_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk); + void emit_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk); + void emit_stmt_breakpoint(const ast::stmt_breakpoint::ptr& stmt, const block::ptr& blk); + void emit_stmt_prof_begin(const ast::stmt_prof_begin::ptr& stmt, const block::ptr& blk); + void emit_stmt_prof_end(const ast::stmt_prof_end::ptr& stmt, const block::ptr& blk); + void emit_expr(const ast::expr& expr, const block::ptr& blk); + void emit_expr_assign(const ast::expr_assign::ptr& expr, const block::ptr& blk); + void emit_expr_clear(const ast::expr& expr, const block::ptr& blk); + void emit_expr_clear_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void emit_expr_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk); + void emit_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk); + void emit_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk); + void emit_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk); + void emit_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk); + void emit_expr_negate(const ast::expr_negate::ptr& expr, const block::ptr& blk); + void emit_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk); + void emit_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_method_pointer(const ast::expr_pointer::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt); + void emit_expr_method_function(const ast::expr_function::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt); + void emit_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); + void emit_expr_parameters(const ast::expr_parameters::ptr& expr, const block::ptr& blk); + void emit_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); + void emit_expr_reference(const ast::expr_reference::ptr& expr, const block::ptr& blk); + void emit_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); + void emit_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void emit_expr_variable_ref(const ast::expr& expr, const block::ptr& blk, bool set); + void emit_expr_array_ref(const ast::expr_array::ptr& expr, const block::ptr& blk, bool set); + void emit_expr_field_ref(const ast::expr_field::ptr& expr, const block::ptr& blk, bool set); + void emit_expr_local_ref(const ast::expr_identifier::ptr& expr, const block::ptr& blk, bool set); + void emit_expr_variable(const ast::expr& expr, const block::ptr& blk); + void emit_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void emit_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void emit_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void emit_expr_object(const ast::expr& expr, const block::ptr& blk); + void emit_expr_vector(const ast::expr_vector::ptr& expr, const block::ptr& blk); + void emit_expr_animation(const ast::expr_animation::ptr& expr); + void emit_expr_animtree(const ast::expr_animtree::ptr& expr); + void emit_expr_istring(const ast::expr_istring::ptr& expr); + void emit_expr_string(const ast::expr_string::ptr& expr); + void emit_expr_float(const ast::expr_float::ptr& expr); + void emit_expr_integer(const ast::expr_integer::ptr& expr); + void emit_expr_false(const ast::expr_false::ptr& expr); + void emit_expr_true(const ast::expr_true::ptr& expr); + void emit_create_local_vars(const block::ptr& blk); + void emit_remove_local_vars(const block::ptr& blk); + void emit_opcode(opcode op); + void emit_opcode(opcode op, const std::string& data); + void emit_opcode(opcode op, const std::vector& data); + void process_thread(const ast::decl_thread::ptr& decl, const block::ptr& blk); + void process_stmt(const ast::stmt& stmt, const block::ptr& blk); + void process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk); + void process_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk); + void process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk); + void process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk); + void process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk); + void process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk); + void process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk); + void process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk); + void process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk); + void process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk); + void process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk); + void process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk); + void process_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk); + void process_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk); + void process_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk); + void process_expr(const ast::expr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_parameters(const ast::expr_parameters::ptr& decl, const block::ptr& blk); + void variable_register(const std::string& name, const block::ptr& blk); + void variable_initialize(const ast::expr_identifier::ptr& name, const block::ptr& blk); + void variable_create(const ast::expr_identifier::ptr& name, const block::ptr& blk); + auto variable_stack_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::uint8_t; + auto variable_create_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string; + auto variable_access_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string; + auto variable_initialized(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> bool; + auto resolve_function_type(const ast::expr_function::ptr& expr) -> ast::call::type; + auto resolve_reference_type(const ast::expr_reference::ptr& expr, bool& method) -> ast::call::type; + auto is_constant_condition(const ast::expr& 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::iw6c diff --git a/src/experimental/iw6c/xsk/context.cpp b/src/experimental/iw6c/xsk/context.cpp new file mode 100644 index 00000000..ec52f856 --- /dev/null +++ b/src/experimental/iw6c/xsk/context.cpp @@ -0,0 +1,23 @@ +// Copyright 2022 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 "iw6c.hpp" + +namespace xsk::gsc::iw6c +{ + +void context::init(build mode, read_cb_type callback) +{ + compiler_.mode(mode); + resolver::init(callback); +} + +void context::cleanup() +{ + resolver::cleanup(); +} + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/context.hpp b/src/experimental/iw6c/xsk/context.hpp new file mode 100644 index 00000000..0c9e3182 --- /dev/null +++ b/src/experimental/iw6c/xsk/context.hpp @@ -0,0 +1,28 @@ +// Copyright 2022 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::iw6c +{ + +class context : public gsc::context +{ + iw6c::assembler assembler_; + iw6c::disassembler disassembler_; + iw6c::compiler compiler_; + iw6c::decompiler decompiler_; + +public: + void init(build mode, read_cb_type callback); + void cleanup(); + + auto assembler() -> gsc::assembler& { return assembler_; } + auto disassembler() -> gsc::disassembler& { return disassembler_; } + auto compiler() -> gsc::compiler& { return compiler_; } + auto decompiler() -> gsc::decompiler& { return decompiler_; } +}; + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/decompiler.cpp b/src/experimental/iw6c/xsk/decompiler.cpp new file mode 100644 index 00000000..3c29a94e --- /dev/null +++ b/src/experimental/iw6c/xsk/decompiler.cpp @@ -0,0 +1,3438 @@ +// Copyright 2022 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 "iw6c.hpp" + +namespace xsk::gsc::iw6c +{ + +auto decompiler::output() -> std::vector +{ + std::vector output; + + auto data = std::make_unique(0x100000); + data->write_string("// IW6 GSC SOURCE\n"); + data->write_string("// 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& funcs) +{ + filename_ = file; + program_ = std::make_unique(); + + for (const auto& func : funcs) + { + auto name = std::make_unique(func->name); + auto params = std::make_unique(); + auto block = std::make_unique(); + func_ = std::make_unique(std::move(name), std::move(params), std::move(block)); + + stack_ = std::stack(); + labels_ = func->labels; + expr_labels_.clear(); + tern_labels_.clear(); + blocks_.clear(); + + decompile_function(func); + + process_stack(func_); + + program_->declarations.push_back(ast::decl(std::move(func_))); + } +} + +void decompiler::decompile_function(const function::ptr& func) +{ + in_waittill_ = false; + + for (const auto& inst : func->instructions) + { + decompile_instruction(inst); + } + + if (stack_.size() > 0) + { + throw decomp_error("stack isn't empty at function end"); + } + + const auto& stmt = func_->stmt; + + block blk; + blk.loc_end = utils::string::va("loc_%X", stmt->list.back().as_node->loc().begin.line); + + // remove last return + stmt->list.pop_back(); + + blocks_.push_back(blk); + + decompile_statements(stmt); + + blocks_.pop_back(); +} + +void decompiler::decompile_instruction(const instruction::ptr& inst) +{ + decompile_expressions(inst); + + auto loc = location(&filename_, inst->index); + + switch (static_cast(inst->opcode)) + { + case opcode::OP_End: + { + auto expr = ast::expr(std::make_unique()); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_Return: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + auto stmt = ast::stmt(std::make_unique(expr.loc(), std::move(expr))); + func_->stmt->list.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 = ast::expr(std::make_unique(loc, inst->data[0])); + auto y = ast::expr(std::make_unique(loc, inst->data[1])); + auto z = ast::expr(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 value = utils::string::unquote(inst->data[0]); + + if (value != "") + { + auto tree = std::make_unique(loc, inst->data[0]); + auto decl = std::make_unique(loc, std::move(tree)); + program_->declarations.push_back(ast::decl(std::move(decl))); + } + + auto node = std::make_unique(loc, utils::string::unquote(inst->data[1])); + stack_.push(std::move(node)); + break; + } + case opcode::OP_GetAnimTree: + { + auto value = utils::string::unquote(inst->data[0]); + + if (value != "") + { + auto tree = std::make_unique(loc, inst->data[0]); + auto decl = std::make_unique(loc, std::move(tree)); + program_->declarations.push_back(ast::decl(std::move(decl))); + } + + 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 path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(path), std::move(name)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_GetLocalFunction: + { + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(path), std::move(name)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_GetFarFunction: + { + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + auto node = std::make_unique(loc, std::move(path), std::move(name)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CreateLocalVariable: + { + if (in_waittill_) + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + else + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + } + break; + } + case opcode::OP_RemoveLocalVariables: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(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 = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalArray: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalNewLocalArrayRefCached0: + { + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLocalArrayRefCached0: + { + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, "0")); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLocalArrayRefCached: + { + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalArrayRef: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ClearArray: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = key.loc(); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(key))); + auto rvalue = ast::expr(std::make_unique(loc)); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_AddArray: + { + auto value = ast::expr(std::move(stack_.top())); stack_.pop(); + auto array = std::move(stack_.top()); stack_.pop(); + + if (array->kind() == ast::kind::expr_empty_array) + { + auto args = std::make_unique(loc); + args->list.push_back(std::move(value)); + auto node = std::make_unique(array->loc(), std::move(args)); + stack_.push(std::move(node)); + } + else if (array->kind() == ast::kind::expr_add_array) + { + (*(ast::expr_add_array::ptr*)&array)->args->list.push_back(std::move(value)); + stack_.push(std::move(array)); + } + else + { + throw 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 path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalFunctionCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalMethodCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(obj) ,std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalChildThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalMethodThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalMethodChildThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarFunctionCall2: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarFunctionCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarMethodCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarChildThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarMethodThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarMethodChildThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFunctionCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptMethodCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = func.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } +/* + case opcode::OP_ScriptChildThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = func.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } +*/ + case opcode::OP_ScriptMethodThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptMethodChildThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = func.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethodPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin0: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin1: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 1u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin2: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 2u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin3: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 3u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin4: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 4u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin5: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 5u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto func = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(func)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod0: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod1: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 1u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj) ,std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod2: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 2u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod3: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 3u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj) ,std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod4: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 4u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod5: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 5u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_DecTop: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + auto stmt = ast::stmt(std::make_unique(expr.loc(), std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_inc: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), false); + stack_.push(std::move(node)); + break; + } + case opcode::OP_dec: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), false); + stack_.push(std::move(node)); + break; + } + case opcode::OP_bit_or: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_bit_ex_or: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_bit_and: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_equality: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_inequality: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_less: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_greater: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_less_equal: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_greater_equal: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_shift_left: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_shift_right: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_plus: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_minus: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_multiply: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_divide: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_mod: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_wait: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = expr.loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_waittillFrameEnd: + { + auto stmt = ast::stmt(std::make_unique(loc)); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_waittill: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = event.as_node->loc(); + auto args = std::make_unique(loc); + auto node = std::make_unique(loc, std::move(obj) , std::move(event), std::move(args)); + stack_.push(std::move(node)); + in_waittill_ = true; + break; + } + case opcode::OP_waittillmatch: + { + auto args = std::make_unique(loc); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = event.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto node = std::move(stack_.top()); stack_.pop(); + loc = node->loc(); + args->list.push_back(std::move(node)); + } + + auto stmt = ast::stmt(std::make_unique(loc, std::move(obj), std::move(event), std::move(args))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_clearparams: + { + if (in_waittill_) + { + auto args = std::make_unique(loc); + auto node = std::move(stack_.top()); stack_.pop(); + + while (node->kind() != ast::kind::stmt_waittill) + { + args->list.push_back(std::move(node)); + node = std::move(stack_.top()); stack_.pop(); + } + + if (node->kind() == ast::kind::stmt_waittill) + { + std::reverse(args->list.begin(), args->list.end()); + (*(ast::stmt_waittill::ptr*)&node)->args = std::move(args); + in_waittill_ = false; + } + + func_->stmt->list.push_back(ast::stmt(std::move(node))); + } + break; + } + case opcode::OP_notify: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto node = std::move(stack_.top()); stack_.pop(); + loc = node->loc(); + + while (node->kind() != ast::kind::asm_voidcodepos) + { + args->list.push_back(std::move(node)); + node = std::move(stack_.top()); stack_.pop(); + loc = node->loc(); + } + + auto stmt = ast::stmt(std::make_unique(loc, std::move(obj), std::move(event), std::move(args))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_endon: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = event.as_node->loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(obj), std::move(event))); + func_->stmt->list.push_back(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 = ast::expr(std::move(stack_.top())); stack_.pop(); + auto y = ast::expr(std::move(stack_.top())); stack_.pop(); + auto z = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = z.as_node->loc(); + auto node = std::make_unique(loc, std::move(x), std::move(y), std::move(z)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_size: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLevelFieldVariable: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalAnimFieldVariable: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalSelfFieldVariable: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalFieldVariable: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLevelFieldVariableRef: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalAnimFieldVariableRef: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalSelfFieldVariableRef: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalFieldVariableRef: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ClearFieldVariable: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + auto name = std::make_unique(loc, inst->data[0]); + auto field = ast::expr(std::make_unique(loc, std::move(obj), std::move(name))); + auto undef = ast::expr(std::make_unique(loc)); + auto expr = ast::expr(std::make_unique(loc, std::move(field), std::move(undef))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SafeCreateVariableFieldCached: + { + auto expr = std::make_unique(loc, "var_" + inst->data[0]); + func_->params->list.push_back(std::move(expr)); + break; + } + case opcode::OP_SafeSetWaittillVariableFieldCached: + { + if (stack_.top()->kind() != ast::kind::asm_create) + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + } + case opcode::OP_SafeSetVariableFieldCached0: + { + auto expr = std::make_unique(loc, "var_0"); + func_->params->list.push_back(std::move(expr)); + break; + } + case opcode::OP_SafeSetVariableFieldCached: + { + auto expr = std::make_unique(loc, "var_" + inst->data[0]); + func_->params->list.push_back(std::move(expr)); + 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 = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetVariableField: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + + if (lvalue.as_node->kind() == ast::kind::expr_increment) + { + auto stmt = ast::stmt(std::make_unique(loc, std::move(lvalue))); + func_->stmt->list.push_back(std::move(stmt)); + } + else if (lvalue.as_node->kind() == ast::kind::expr_decrement) + { + auto stmt = ast::stmt(std::make_unique(loc, std::move(lvalue))); + func_->stmt->list.push_back(std::move(stmt)); + } + else + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + } + break; + } + case opcode::OP_SetAnimFieldVariableField: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetSelfFieldVariableField: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetLocalVariableFieldCached0: + { + auto lvalue = ast::expr(std::make_unique(loc, "0")); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetNewLocalVariableFieldCached0: + { + auto lvalue = ast::expr(std::make_unique(loc, inst->data[0])); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + + if (func_->stmt->list.size() > 0) + { + std::vector vars; + + while (func_->stmt->list.back().as_node->kind() == ast::kind::asm_create) + { + auto& entry = func_->stmt->list.back(); + if (loc.begin.line < entry.as_node->loc().begin.line) + { + vars.push_back(entry.as_asm_create->index); + func_->stmt->list.pop_back(); + continue; + } + break; + } + + std::reverse(vars.begin(), vars.end()); + lvalue.as_asm_create->vars = vars; + } + + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetLocalVariableFieldCached: + { + auto lvalue = ast::expr(std::make_unique(loc, inst->data[0])); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_ClearLocalVariableFieldCached: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_ClearLocalVariableFieldCached0: + { + auto stmt = ast::stmt(std::make_unique(loc, "0")); + func_->stmt->list.push_back(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_BoolNot: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_BoolComplement: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_switch: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = expr.as_node->loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr), inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_endswitch: + { + auto count = inst->data[0]; + inst->data.erase(inst->data.begin()); + auto data = inst->data; + auto stmt = ast::stmt(std::make_unique(loc, data, count)); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_jump: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + if (stack_.size() != 0) tern_labels_.push_back(inst->data[0]); + break; + } + case opcode::OP_jumpback: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_JumpOnTrue: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr), inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_JumpOnFalse: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(lvalue), inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_JumpOnTrueExpr: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), inst->data[0]); + stack_.push(std::move(node)); + expr_labels_.push_back(inst->data[0]); + break; + } + case opcode::OP_JumpOnFalseExpr: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), inst->data[0]); + stack_.push(std::move(node)); + expr_labels_.push_back(inst->data[0]); + break; + } +// case opcode::OP_waittillmatch2: + case opcode::OP_checkclearparams: + case opcode::OP_CastFieldObject: + case opcode::OP_CastBool: + break; + // case opcode::OP_ClearVariableField + // case opcode::OP_EvalNewLocalVariableRefCached0 + default: + throw decomp_error("unhandled opcode " + resolver::opcode_name(inst->opcode)); + } +} + +void decompiler::decompile_expressions(const instruction::ptr& inst) +{ + const auto itr = labels_.find(inst->index); + + if (itr == labels_.end()) + return; + + for (const auto& expr : expr_labels_) + { + if (expr == itr->second) + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto jump = std::move(stack_.top()); stack_.pop(); + auto loc = jump->loc(); + + if (jump->kind() == ast::kind::asm_jump_true_expr) + { + auto lvalue = std::move((*(ast::asm_jump_true_expr::ptr*)&jump)->expr); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + } + else if (jump->kind() == ast::kind::asm_jump_false_expr) + { + auto lvalue = std::move((*(ast::asm_jump_false_expr::ptr*)&jump)->expr); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + } + else + { + throw decomp_error("TRIED TO DECOMPILE INVALID JUMP EXPR!"); + } + } + } + + for (const auto& tern : tern_labels_) + { + if (tern == itr->second) + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + + func_->stmt->list.pop_back(); + auto stmt = std::move(func_->stmt->list.back()); + func_->stmt->list.pop_back(); + + if (stmt == ast::kind::asm_jump_cond) + { + auto loc = stmt.as_cond->loc(); + auto node = std::make_unique(loc, std::move(stmt.as_cond->expr), std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + } + else + { + throw decomp_error("TRIED TO DECOMPILE INVALID TERNARY EXPR!"); + } + } + } +} + +void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) +{ + decompile_loops(stmt); + decompile_switches(stmt); + decompile_ifelses(stmt); + decompile_aborts(stmt); + decompile_tuples(stmt); +} + +void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) +{ + if (stmt->list.size() == 0) + return; + + for (auto i = static_cast(stmt->list.size() - 1); i >= 0; i--) + { + if (stmt->list.at(i) == ast::kind::asm_jump_back) + { + auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); + auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); + + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + if (i - 1 == static_cast(start)) // condition belongs to empty loop + { + decompile_while(stmt, start, i); + i = static_cast(stmt->list.size()); + continue; + } + else if (static_cast(i) < find_location_index(stmt, stmt->list.at(i - 1).as_cond->value)) + { + decompile_dowhile(stmt, i - 1, i); + i = static_cast(stmt->list.size()); + continue; + } + } + + if (i == static_cast(start)) // empty inf loop + { + decompile_inf(stmt, start, i); + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) // no condition + { + decompile_inf(stmt, start, i); + } + else if (stmt->list.at(start).as_cond->value != break_loc) // condition belong to other stmt + { + decompile_inf(stmt, start, i); + } + else // condition belong to loop + { + decompile_loop(stmt, start, i); + } + + i = static_cast(stmt->list.size()); + } + } +} + +void decompiler::decompile_switches(const ast::stmt_list::ptr& stmt) +{ + for (auto i = 0u; i < stmt->list.size(); i++) + { + if (stmt->list.at(i) == ast::kind::asm_switch) + { + decompile_switch(stmt, i); + } + } +} + +void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) +{ + for (auto i = 0u; i < stmt->list.size(); i++) + { + const auto& entry = stmt->list.at(i); + + if (entry == ast::kind::asm_jump_cond) + { + auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); + auto last_loc = blocks_.back().loc_end; + + if (stmt->list.at(j) == ast::kind::asm_jump) + { + // if block is a loop check break, continue + if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) + { + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } + } + else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) + { + decompile_if(stmt, i, j); + } + else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) + { + if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) + { + // if block, have a empty else inside at end + decompile_if(stmt, i, j); + } + else + { + decompile_ifelse(stmt, i, j); // if block with empty else + } + } + else + { + decompile_ifelse(stmt, i, j); + } + } + else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) + { + if(entry.as_cond->value != blocks_.back().loc_end) + { + auto ref = stmt->list.at(j + 1).loc().label(); + + if (find_location_reference(stmt, i + 1, j, ref)) + { + // after return is referenced inside the block + decompile_if(stmt, i, j); + continue; + } + } + + if (blocks_.back().loc_break != "" || blocks_.back().loc_continue != "") + { + decompile_if(stmt, i, j); // inside a loop cant be last + } + else if (j - i == 1) + { + decompile_if(stmt, i, j); // only one explicit return + } + else if (stmt->list.back().as_node->kind() != ast::kind::stmt_return) + { + decompile_if(stmt, i, j); // block end is not a last return + } + else if (blocks_.back().is_last && stmt->list.back().as_node->kind() != ast::kind::stmt_return) + { + decompile_if(stmt, i, j); // inside a last block but is not and inner last + } + else if (find_location_reference(stmt, j, stmt->list.size(), last_loc)) + { + decompile_if(stmt, i, j); // reference to func end after the if + } + else if (blocks_.size() > 1 && !blocks_.back().is_last) + { + decompile_if(stmt, i, j); // fake last ifelse + } + else + { + decompile_ifelse_end(stmt, i, j); // special case + } + } + else + { + decompile_if(stmt, i, j); + } + } + } +} + +void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) +{ + for (auto i = 0u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_jump) + { + auto loc = block->list.at(i).loc(); + auto jump_loc = block->list.at(i).as_jump->value; + + if (jump_loc == blocks_.back().loc_continue) + { + block->list.erase(block->list.begin() + i); + auto stmt = ast::stmt(std::make_unique(loc)); + block->list.insert(block->list.begin() + i, std::move(stmt)); + } + else if (jump_loc == blocks_.back().loc_break) + { + block->list.erase(block->list.begin() + i); + auto stmt = ast::stmt(std::make_unique(loc)); + block->list.insert(block->list.begin() + i, std::move(stmt)); + } + else + { + std::cout << "WARNING: unresolved jump to '" + jump_loc + "', maybe incomplete for loop\n"; + } + } + } +} + +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + const auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + +void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_end = stmt->list.at(begin).as_cond->value; + blk.loc_break = blocks_.back().loc_break; + blk.loc_continue = blocks_.back().loc_continue; + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + + auto if_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + if_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(if_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block if_blk; + if_blk.loc_end = stmt->list.at(end).loc().label(); + if_blk.loc_break = blocks_.back().loc_break; + if_blk.loc_continue = blocks_.back().loc_continue; + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end--; + + auto if_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + if_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(if_blk); + decompile_statements(if_stmt); + blocks_.pop_back(); + + auto end_loc = stmt->list.at(begin).as_jump->value; + stmt->list.erase(stmt->list.begin() + begin); // remove 'jump' + + auto end_idx = (end_loc == blocks_.back().loc_end) ? stmt->list.size() : find_location_index(stmt, end_loc); + + block else_blk; + else_blk.loc_end = end_loc; + else_blk.loc_break = blocks_.back().loc_break; + else_blk.loc_continue = blocks_.back().loc_continue; + + auto else_stmt = std::make_unique(loc); + + for (auto i = begin; i < end_idx; i++) + { + else_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(else_blk); + decompile_statements(else_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)), ast::stmt(std::move(else_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_ifelse_end(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block if_blk; + if_blk.is_last = true; + + auto if_end = find_location_index(stmt, stmt->list.at(begin).as_cond->value) - 1; + if_blk.loc_end = stmt->list.at(if_end).loc().label(); + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end--; + + auto if_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + if_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + stmt->list.erase(stmt->list.begin() + begin); // remove 'return' + + blocks_.push_back(if_blk); + decompile_statements(if_stmt); + blocks_.pop_back(); + + if (begin == stmt->list.size()) + { + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); + } + else + { + block else_blk; + else_blk.is_last = true; + + end = stmt->list.size() - 1; + else_blk.loc_end = stmt->list.at(end).loc().label(); + + auto else_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + else_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + stmt->list.erase(stmt->list.begin() + begin); // remove 'return' + + blocks_.push_back(else_blk); + decompile_statements(else_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)), ast::stmt(std::move(else_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); + } +} + +void decompiler::decompile_inf(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = last_location_index(stmt, end) ? blocks_.back().loc_end : stmt->list.at(end + 1).loc().label(); + blk.loc_end = stmt->list.at(end).loc().label(); + blk.loc_continue = stmt->list.at(end).loc().label(); + + auto loc = stmt->list.at(begin).loc(); + + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto for_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + for_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(for_stmt); + blocks_.pop_back(); + + auto init = ast::stmt(std::make_unique()); + auto test = ast::expr(std::make_unique()); + auto iter = ast::stmt(std::make_unique()); + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(init), std::move(test), std::move(iter), ast::stmt(std::move(for_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_loop(const ast::stmt_list::ptr& block, std::size_t start, std::size_t end) +{ + const auto& last = block->list.at(end - 1); + + if (last == ast::kind::stmt_assign) + { + if (last.as_assign->expr == ast::kind::expr_assign_equal) + { + auto& call = last.as_assign->expr.as_assign_equal->rvalue; + + if (call == ast::kind::expr_call && call.as_call->call == ast::kind::expr_function) + { + if (utils::string::to_lower(call.as_call->call.as_function->name->value) == "getnextarraykey") + { + auto ref = block->list.at(start).loc().label(); + + if (!find_location_reference(block, 0, start, ref)) + { + decompile_foreach(block, start, end); + return; + } + } + } + } + + if (start > 0) // while at func start + { + auto index = 1; + while (block->list.at(start - index) == ast::kind::asm_create) + { + if (start - index > 0) + index++; + else + break; + } + + if (block->list.at(start - index) == ast::kind::stmt_assign) + { + auto ref = block->list.at(end).loc().label(); + auto ref2 = block->list.at(start - index + 1).loc().label(); + + 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 or localVarCreate, 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 ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(end).loc().label(); + blk.loc_continue = stmt->list.at(end).loc().label(); + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end--; + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(end - 1).loc().label(); + blk.loc_continue = stmt->list.at(end - 1).loc().label(); + + // collect local vars + std::vector vars; + while (stmt->list.at(begin - 1) == ast::kind::asm_create) + { + vars.push_back(stmt->list.at(begin - 1).as_asm_create->index); + stmt->list.erase(stmt->list.begin() + begin - 1); + begin--; + end--; + } + + std::reverse(vars.begin(), vars.end()); + + auto loc = stmt->list.at(begin - 1).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + auto init = ast::stmt(std::make_unique()); + init.as_list->list.push_back(std::move(stmt->list.at(begin - 1))); + init.as_list->is_expr = true; + + auto iter = ast::stmt(std::make_unique()); + iter.as_list->list.push_back(std::move(stmt->list.at(end - 1))); + iter.as_list->is_expr = true; + + begin--; // move begin from 'test' to 'init' + stmt->list.erase(stmt->list.begin() + begin); // remove 'init' + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end -= 3; // move end to 'iter' ( minus 'init' & 'test' ) + stmt->list.erase(stmt->list.begin() + end); // remove 'iter' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto for_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + for_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(for_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(init), std::move(test), std::move(iter), ast::stmt(std::move(for_stmt)))); + new_stmt.as_for->vars = vars; + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_foreach(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(end - 1).loc().label(); + blk.loc_continue = stmt->list.at(end - 1).loc().label(); + + // collect local vars + std::vector vars; + while (stmt->list.at(begin - 1) == ast::kind::asm_create) + { + vars.push_back(stmt->list.at(begin - 1).as_asm_create->index); + stmt->list.erase(stmt->list.begin() + begin - 1); + begin--; + end--; + } + + std::reverse(vars.begin(), vars.end()); + + auto loc = stmt->list.at(begin - 2).loc(); + + auto init = ast::stmt(std::make_unique()); + init.as_list->list.push_back(std::move(stmt->list[begin-2])); + init.as_list->list.push_back(std::move(stmt->list[begin-1])); + auto stmt0 = std::move(stmt->list[begin+1]); + + begin -= 2; // move begin from 'test' to 'array' + stmt->list.erase(stmt->list.begin() + begin); // remove 'array' + stmt->list.erase(stmt->list.begin() + begin); // remove 'elem' + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + stmt->list.erase(stmt->list.begin() + begin); // remove 'set' + end -= 5; // move end to 'iter' ( minus 'array', 'elem', 'test' & 'set' ) + stmt->list.erase(stmt->list.begin() + end); // remove 'iter' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback + + if (stmt->list.size() > end && stmt->list.at(end) == ast::kind::asm_clear) + { + stmt->list.erase(stmt->list.begin() + end); // remove temp var 'array' + } + + auto use_key = true; + + if (stmt->list.size() > end && stmt->list.at(end) == ast::kind::asm_clear) + { + stmt->list.erase(stmt->list.begin() + end); // remove temp var 'key' + use_key = false; + } + + auto foreach_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + foreach_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(foreach_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, ast::stmt(std::move(foreach_stmt)), use_key)); + new_stmt.as_foreach->vars = vars; + new_stmt.as_foreach->pre_expr = std::move(init); + new_stmt.as_foreach->stmt0 = std::move(stmt0); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_switch(const ast::stmt_list::ptr& stmt, std::size_t start) +{ + block blk; + blk.loc_continue = blocks_.back().loc_continue; + blk.loc_end = stmt->list.at(start).as_asm_switch->value; + + auto loc = stmt->list.at(start).loc(); + auto test = std::move(stmt->list.at(start).as_asm_switch->expr); + auto end_loc = stmt->list.at(start).as_asm_switch->value; + auto end = find_location_index(stmt, end_loc); + + blk.loc_break = (end == stmt->list.size() - 1) ? blocks_.back().loc_end : stmt->list.at(end + 1).loc().label(); + + // collect cases + auto casenum = std::atol(stmt->list.at(end).as_asm_endswitch->count.data()); + auto data = stmt->list.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(stmt, loc_str); + auto loc_pos = location(&filename_, std::stol(loc_str.substr(4), 0, 16)); + auto value = ast::expr(std::make_unique(loc_pos, data.at(idx + 1))); + auto list = std::make_unique(loc); + list->is_case = true; + auto case_stmt = ast::stmt(std::make_unique(loc_pos, std::move(value), std::move(list))); + stmt->list.insert(stmt->list.begin() + loc_idx, std::move(case_stmt)); + idx += 3; + } + else if (data.at(idx) == "default") + { + auto loc_str = data.at(idx + 1); + auto loc_idx = find_location_index(stmt, loc_str); + auto loc_pos = location(&filename_, std::stol(loc_str.substr(4), 0, 16)); + auto list = std::make_unique(loc); + list->is_case = true; + auto def_stmt = ast::stmt(std::make_unique(loc_pos, std::move(list))); + while (stmt->list.at(loc_idx) == ast::kind::stmt_case) + loc_idx++; + stmt->list.insert(stmt->list.begin() + loc_idx, std::move(def_stmt)); + idx += 2; + } + } + + end = find_location_index(stmt, end_loc); // update end + + while (stmt->list.size() > (end + 1) && stmt->list.at(end) != ast::kind::asm_endswitch) + end++; + + if (stmt->list.at(end) != ast::kind::asm_endswitch) + decomp_error("bad empty cases in switch block!"); + + end--; + stmt->list.erase(stmt->list.begin() + start); // remove 'switch' + stmt->list.erase(stmt->list.begin() + end); // remove 'endswitch' + + //decompile block + auto sw_stmt = std::make_unique(loc); + + for (auto i = start; i < end; i++) + { + sw_stmt->list.push_back(std::move(stmt->list[start])); + stmt->list.erase(stmt->list.begin() + start); + } + + blocks_.push_back(blk); + decompile_statements(sw_stmt); + blocks_.pop_back(); + + auto stmt_list = std::make_unique(loc); + auto current_case = ast::stmt(std::make_unique()); + + auto num = sw_stmt->list.size(); + for (auto i = 0u; i < num; i++) + { + auto& entry = sw_stmt->list[0]; + + if (entry == ast::kind::stmt_case || entry == ast::kind::stmt_default) + { + if (current_case.kind() != ast::kind::null) + { + stmt_list->list.push_back(std::move(current_case)); + } + + current_case = std::move(sw_stmt->list[0]); + sw_stmt->list.erase(sw_stmt->list.begin()); + } + else + { + if (current_case.kind() != ast::kind::null) + { + if (current_case == ast::kind::stmt_case) + { + current_case.as_case->stmt->list.push_back(std::move(sw_stmt->list[0])); + sw_stmt->list.erase(sw_stmt->list.begin()); + } + else + { + current_case.as_default->stmt->list.push_back(std::move(sw_stmt->list[0])); + sw_stmt->list.erase(sw_stmt->list.begin()); + } + } + else + { + decomp_error("missing case before stmt inside switch!"); + } + } + } + + if (current_case.kind() != ast::kind::null) + { + stmt_list->list.push_back(std::move(current_case)); + } + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), std::move(stmt_list))); + stmt->list.insert(stmt->list.begin() + start, std::move(new_stmt)); +} + +auto decompiler::find_location_reference(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end, const std::string& location) -> bool +{ + for (auto i = begin; i < end; i++) + { + const auto& entry = stmt->list.at(i); + + if (entry == ast::kind::asm_jump_cond && entry.as_cond->value == location) + { + return true; + } + else if (entry == ast::kind::asm_jump && entry.as_jump->value == location) + { + return true; + } + } + + return false; +} + +auto decompiler::find_location_index(const ast::stmt_list::ptr& stmt, const std::string& location) -> std::size_t +{ + auto index = 0u; + + if (location == blocks_.back().loc_end) + return stmt->list.size(); + + for (const auto& entry : stmt->list) + { + if (entry.loc().label() == location) + return index; + + index++; + } + + throw decomp_error("LOCATION NOT FOUND! (" + location + ")"); +} + +auto decompiler::last_location_index(const ast::stmt_list::ptr& stmt, std::size_t index) -> bool +{ + if (index == stmt->list.size() - 1) + return true; + + return false; +} + +void decompiler::process_stack(const ast::decl_thread::ptr& thread) +{ + auto blk = std::make_unique(); + + process_parameters(thread->params, blk); + process_stmt_list(thread->stmt, blk); +} + +void decompiler::process_parameters(const ast::expr_parameters::ptr& params, const block::ptr& blk) +{ + for (const auto& entry : params->list) + { + blk->local_vars.push_back({ entry->value, static_cast(std::stoi(entry->value.substr(4))), true }); + blk->local_vars_create_count++; + } +} + +void decompiler::process_stmt(const ast::stmt& stmt, const block::ptr& blk) +{ + switch (stmt.kind()) + { + case ast::kind::stmt_list: + process_stmt_list(stmt.as_list, blk); + break; + case ast::kind::stmt_expr: + process_stmt_expr(stmt.as_expr, blk); + break; + case ast::kind::stmt_call: + process_stmt_call(stmt.as_call, blk); + break; + case ast::kind::stmt_assign: + process_stmt_assign(stmt.as_assign, blk); + break; + case ast::kind::stmt_endon: + process_stmt_endon(stmt.as_endon, blk); + break; + case ast::kind::stmt_notify: + process_stmt_notify(stmt.as_notify, blk); + break; + case ast::kind::stmt_wait: + process_stmt_wait(stmt.as_wait, blk); + break; + case ast::kind::stmt_waittill: + process_stmt_waittill(stmt.as_waittill, blk); + break; + case ast::kind::stmt_waittillmatch: + process_stmt_waittillmatch(stmt.as_waittillmatch, blk); + break; + case ast::kind::stmt_if: + process_stmt_if(stmt.as_if, blk); + break; + case ast::kind::stmt_ifelse: + process_stmt_ifelse(stmt.as_ifelse, blk); + break; + case ast::kind::stmt_while: + process_stmt_while(stmt.as_while, blk); + break; + case ast::kind::stmt_dowhile: + process_stmt_dowhile(stmt.as_dowhile, blk); + break; + case ast::kind::stmt_for: + process_stmt_for(stmt.as_for, blk); + break; + case ast::kind::stmt_foreach: + process_stmt_foreach(stmt.as_foreach, blk); + break; + case ast::kind::stmt_switch: + process_stmt_switch(stmt.as_switch, blk); + break; + case ast::kind::stmt_break: + process_stmt_break(stmt.as_break, blk); + break; + case ast::kind::stmt_continue: + process_stmt_continue(stmt.as_continue, blk); + break; + case ast::kind::stmt_return: + process_stmt_return(stmt.as_return, blk); + break; + case ast::kind::asm_remove: + process_var_remove(stmt.as_asm_remove, blk); + break; + case ast::kind::asm_create: + { + auto expr = ast::expr(std::make_unique(stmt.as_asm_create->index)); + process_var_create(expr, blk, true); + break; + } + default: + break; + } +} + +void decompiler::process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk) +{ + for (const auto& entry : stmt->list) + { + process_stmt(entry, blk); + } + + auto i = 0u; + + while (i < stmt->list.size()) + { + auto type = stmt->list.at(i).kind(); + + if (type == ast::kind::asm_create || type == ast::kind::asm_remove) + { + stmt->list.erase(stmt->list.begin() + i); + continue; + } + + i++; + } +} + +void decompiler::process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr_increment(stmt->expr.as_increment, blk); + break; + case ast::kind::expr_decrement: + process_expr_decrement(stmt->expr.as_decrement, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr_assign(stmt->expr.as_assign, blk); + break; + default: + break; + } +} + +void decompiler::process_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_call: + process_expr_call(stmt->expr.as_call, blk); + break; + case ast::kind::expr_method: + process_expr_method(stmt->expr.as_method, blk); + break; + default: + break; + } +} + +void decompiler::process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr_increment(stmt->expr.as_increment, blk); + break; + case ast::kind::expr_decrement: + process_expr_decrement(stmt->expr.as_decrement, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr_assign(stmt->expr.as_assign, blk); + break; + default: + break; + } +} + +void decompiler::process_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->event, blk); + process_expr(stmt->obj, blk); +} + +void decompiler::process_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk) +{ + process_expr_arguments(stmt->args, blk); + process_expr(stmt->event, blk); + process_expr(stmt->obj, blk); +} + +void decompiler::process_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->time, blk); +} + +void decompiler::process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->event ,blk); + process_expr(stmt->obj, blk); + + for (auto& entry : stmt->args->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk) +{ + process_expr_arguments(stmt->args, blk); + process_expr(stmt->event, blk); + process_expr(stmt->obj, blk); +} + +void decompiler::process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_stmt(stmt->stmt, stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk) +{ + std::vector childs; + auto abort = abort_t::abort_return; + + process_expr(stmt->test, blk); + + stmt->blk_if = std::make_unique(); + blk->transfer_decompiler(stmt->blk_if); + + process_stmt(stmt->stmt_if, stmt->blk_if); + + if (stmt->blk_if->abort <= abort_t::abort_return) + { + abort = stmt->blk_if->abort; + + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_if.get()); + } + + stmt->blk_else = std::make_unique(); + blk->transfer_decompiler(stmt->blk_else); + + process_stmt(stmt->stmt_else, stmt->blk_else); + + if (stmt->blk_else->abort <= abort) + { + abort = stmt->blk_else->abort; + + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_else.get()); + } + + if (blk->abort == abort_t::abort_none) + blk->abort = abort; + + blk->append(childs); + + if (stmt->stmt_if.as_list->list.size() == 1 && !stmt->stmt_if.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt_if = std::move(stmt->stmt_if.as_list->list.back()); + } + + if (stmt->stmt_else.as_list->list.size() == 1 && !stmt->stmt_else.as_list->list.at(0).as_node->is_special_stmt_noif()) + { + stmt->stmt_else = std::move(stmt->stmt_else.as_list->list.back()); + } +} + +void decompiler::process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_stmt(stmt->stmt, stmt->blk); + + std::vector childs({ stmt->blk.get() }); + + if (stmt->test.as_node->kind() == ast::kind::null) + blk->append_decompiler(stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_stmt(stmt->stmt, stmt->blk); + + std::vector childs({ stmt->blk.get() }); + + if (stmt->test.as_node->kind() == ast::kind::null) + blk->append_decompiler(stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk) +{ + process_stmt(stmt->init, blk); + + for (const auto& index : stmt->vars) + { + auto var = utils::string::va("var_%d", std::stoi(index)); + blk->local_vars.push_back({ var, static_cast(std::stoi(index)), true }); + blk->local_vars_create_count++; + } + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_expr(stmt->test, blk); + + process_stmt(stmt->stmt, stmt->blk); + + process_stmt(stmt->iter, blk); + + if (stmt->test == ast::kind::null) + blk->append_decompiler(stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk) +{ + process_stmt(stmt->pre_expr, blk); + + for (const auto& index : stmt->vars) + { + auto var1 = utils::string::va("var_%d", std::stoi(index)); + blk->local_vars.push_back({ var1, static_cast(std::stoi(index)), true }); + blk->local_vars_create_count++; + } + + stmt->ctx = std::make_unique(); + blk->transfer_decompiler(stmt->ctx); + + process_stmt(stmt->stmt0, stmt->ctx); + process_stmt(stmt->stmt, stmt->ctx); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } + + stmt->array_expr = std::move(stmt->pre_expr.as_list->list[0].as_assign->expr.as_assign->rvalue); + stmt->value_expr = std::move(stmt->stmt0.as_assign->expr.as_assign->lvalue); + stmt->key_expr = std::move(stmt->pre_expr.as_list->list[1].as_assign->expr.as_assign->lvalue); +} + +void decompiler::process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->ctx = std::make_unique(); + blk->transfer_decompiler(stmt->ctx); + + process_stmt_cases(stmt->stmt, stmt->ctx); + + blk->append_decompiler(stmt->ctx, true); +} + +void decompiler::process_stmt_cases(const ast::stmt_list::ptr& stmt, const block::ptr& blk) +{ + std::vector childs; + bool has_default = false; + + for (const auto& entry : stmt->list) + { + if (entry == ast::kind::stmt_case) + { + entry.as_case->blk = std::make_unique(); + blk->transfer_decompiler(entry.as_case->blk); + + process_stmt_list(entry.as_case->stmt, entry.as_case->blk); + + if (entry.as_case->blk->abort == abort_t::abort_break) + { + childs.push_back(entry.as_case->blk.get()); + } + } + else if (entry == ast::kind::stmt_default) + { + has_default = true; + entry.as_default->blk = std::make_unique(); + blk->transfer_decompiler(entry.as_default->blk); + + process_stmt_list(entry.as_default->stmt, entry.as_default->blk); + + if (entry.as_default->blk->abort == abort_t::abort_break) + { + childs.push_back(entry.as_default->blk.get()); + } + } + } + + if (has_default) + { + blk->append(childs); + } +} + +void decompiler::process_stmt_break(const ast::stmt_break::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_break; + } +} + +void decompiler::process_stmt_continue(const ast::stmt_continue::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_continue; + } +} + +void decompiler::process_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_return; + } + + if (stmt->expr != ast::kind::null) + { + process_expr(stmt->expr, blk); + } +} + +void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_ternary: + process_expr_ternary(expr.as_ternary, blk); + break; + case ast::kind::expr_and: + process_expr_and(expr.as_and, blk); + break; + case ast::kind::expr_or: + process_expr_or(expr.as_or, blk); + break; + case ast::kind::expr_equality: + case ast::kind::expr_inequality: + case ast::kind::expr_less: + case ast::kind::expr_greater: + case ast::kind::expr_less_equal: + case ast::kind::expr_greater_equal: + case ast::kind::expr_bitwise_or: + case ast::kind::expr_bitwise_and: + case ast::kind::expr_bitwise_exor: + case ast::kind::expr_shift_left: + case ast::kind::expr_shift_right: + case ast::kind::expr_add: + case ast::kind::expr_sub: + case ast::kind::expr_mul: + case ast::kind::expr_div: + case ast::kind::expr_mod: + process_expr_binary(expr.as_binary, blk); + break; + case ast::kind::expr_complement: + process_expr_complement(expr.as_complement, blk); + break; + case ast::kind::expr_not: + process_expr_not(expr.as_not, blk); + break; + case ast::kind::expr_call: + process_expr_call(expr.as_call, blk); + break; + case ast::kind::expr_method: + process_expr_method(expr.as_method, blk); + break; + case ast::kind::expr_add_array: + process_expr_add_array(expr.as_add_array, blk); + break; + case ast::kind::expr_size: + process_expr_size(expr.as_size, blk); + break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; + case ast::kind::expr_vector: + process_expr_vector(expr.as_vector, blk); + break; + case ast::kind::asm_create: + process_var_create(expr, blk); + break; + case ast::kind::asm_access: + process_var_access(expr, blk); + break; + default: + break; + } +} + +void decompiler::process_expr_assign(ast::expr_assign::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->rvalue, blk); + process_expr(expr->lvalue, blk); + + if (expr->kind() == ast::kind::expr_assign_equal) + { + switch (expr->rvalue.kind()) + { + case ast::kind::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_bitwise_or->rvalue)); + break; + case ast::kind::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_bitwise_and->rvalue)); + break; + case ast::kind::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_bitwise_exor->rvalue)); + break; + case ast::kind::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_shift_left->rvalue)); + break; + case ast::kind::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_shift_right->rvalue)); + break; + case ast::kind::expr_add: + if (expr->lvalue == expr->rvalue.as_add->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_add->rvalue)); + break; + case ast::kind::expr_sub: + if (expr->lvalue == expr->rvalue.as_sub->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_sub->rvalue)); + break; + case ast::kind::expr_mul: + if (expr->lvalue == expr->rvalue.as_mul->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mul->rvalue)); + break; + case ast::kind::expr_div: + if (expr->lvalue == expr->rvalue.as_div->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_div->rvalue)); + break; + case ast::kind::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_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); +} + +void decompiler::process_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); +} + +void decompiler::process_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->test, blk); + process_expr(expr->true_expr, blk); + process_expr(expr->false_expr, blk); +} + +void decompiler::process_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); + process_expr(expr->rvalue, blk); + + auto prec = expr->lvalue.as_node->precedence(); + + if (prec && prec < expr->precedence()) + { + expr->lvalue = ast::expr(std::make_unique(std::move(expr->lvalue))); + } + + prec = expr->rvalue.as_node->precedence(); + + if ((prec && prec < expr->precedence()) || (prec == expr->precedence() && expr->kind() == expr->rvalue.as_node->kind())) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); + process_expr(expr->rvalue, blk); + + auto prec = expr->lvalue.as_node->precedence(); + + if (prec && prec < expr->precedence()) + { + expr->lvalue = ast::expr(std::make_unique(std::move(expr->lvalue))); + } + + prec = expr->rvalue.as_node->precedence(); + + if ((prec && prec < expr->precedence()) || (prec == expr->precedence() && expr->kind() == expr->rvalue.kind())) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); + process_expr(expr->rvalue, blk); +} + +void decompiler::process_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->rvalue, blk); + + if (expr->rvalue.as_node->is_binary()) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->rvalue, blk); + + if (expr->rvalue.as_node->is_binary()) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk) +{ + switch (expr->call.kind()) + { + case ast::kind::expr_pointer: + process_expr_call_pointer(expr->call.as_pointer, blk); + break; + case ast::kind::expr_function: + process_expr_call_function(expr->call.as_function, blk); + break; + default: + break; + } +} + +void decompiler::process_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk) +{ + switch (expr->call.kind()) + { + case ast::kind::expr_pointer: + process_expr_method_pointer(expr->call.as_pointer, expr->obj, blk); + break; + case ast::kind::expr_function: + process_expr_method_function(expr->call.as_function, expr->obj, blk); + break; + default: + break; + } +} + +void decompiler::process_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); + process_expr(expr->func, blk); +} + +void decompiler::process_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); +} + +void decompiler::process_expr_method_pointer(const ast::expr_pointer::ptr& expr, ast::expr& obj, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); + process_expr(obj, blk); + process_expr(expr->func, blk); +} + +void decompiler::process_expr_method_function(const ast::expr_function::ptr& expr, ast::expr& obj, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); + process_expr(obj, blk); +} + +void decompiler::process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk) +{ + for (auto i = expr->list.size(); i > 0; i--) + { + process_expr(expr->list.at(i - 1), blk); + } +} + +void decompiler::process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk) +{ + for (auto& entry : expr->args->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->obj, blk); +} + +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->key, blk); + process_expr(expr->obj, blk); +} + +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->obj, blk); +} + +void decompiler::process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk) +{ + process_expr(vec->z, blk); + process_expr(vec->y, blk); + process_expr(vec->x, blk); +} + +void decompiler::process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt) +{ + if (fromstmt) + { + auto var = utils::string::va("var_%d", std::stoi(expr.as_asm_create->index)); + blk->local_vars.push_back({ var, static_cast(std::stoi(expr.as_asm_create->index)), true }); + blk->local_vars_create_count++; + } + else + { + for (const auto& entry : expr.as_asm_create->vars) + { + blk->local_vars.push_back({ utils::string::va("var_%d", std::stoi(entry)), static_cast(std::stoi(entry)), true }); + blk->local_vars_create_count++; + } + + auto var = utils::string::va("var_%d", std::stoi(expr.as_asm_create->index)); + blk->local_vars.push_back({ var, static_cast(std::stoi(expr.as_asm_create->index)), true }); + blk->local_vars_create_count++; + + expr = ast::expr(std::make_unique(var)); + } +} + +void decompiler::process_var_access(ast::expr& expr, const block::ptr& blk) +{ + if (blk->local_vars.size() <= std::stoul(expr.as_asm_access->index)) + { + std::cout << "WARNING: bad local var access\n"; + } + else + { + auto var = blk->local_vars.at(blk->local_vars.size() - 1 - std::stoi(expr.as_asm_access->index)).name; + expr = ast::expr(std::make_unique(var)); + } +} + +void decompiler::process_var_remove(const ast::asm_remove::ptr& expr, const block::ptr& blk) +{ + blk->local_vars_public_count = static_cast(blk->local_vars.size() - std::stoi(expr->index)); +} + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/decompiler.hpp b/src/experimental/iw6c/xsk/decompiler.hpp new file mode 100644 index 00000000..dc740bb0 --- /dev/null +++ b/src/experimental/iw6c/xsk/decompiler.hpp @@ -0,0 +1,101 @@ +// Copyright 2022 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::iw6c +{ + +class decompiler : public gsc::decompiler +{ + std::string filename_; + ast::program::ptr program_; + ast::decl_thread::ptr func_; + std::unordered_map labels_; + std::vector expr_labels_; + std::vector tern_labels_; + std::stack stack_; + std::vector blocks_; + bool in_waittill_; + +public: + auto output() -> std::vector; + void decompile(const std::string& file, std::vector& funcs); + +private: + void decompile_function(const function::ptr& func); + void decompile_instruction(const instruction::ptr& inst); + void decompile_expressions(const instruction::ptr& inst); + void decompile_statements(const ast::stmt_list::ptr& stmt); + void decompile_loops(const ast::stmt_list::ptr& stmt); + void decompile_switches(const ast::stmt_list::ptr& stmt); + void decompile_ifelses(const ast::stmt_list::ptr& stmt); + void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); + void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_ifelse_end(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_inf(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_loop(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_while(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_for(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_foreach(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_switch(const ast::stmt_list::ptr& stmt, std::size_t begin); + auto find_location_reference(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end, const std::string& location) -> bool; + auto find_location_index(const ast::stmt_list::ptr& stmt, const std::string& location) -> std::size_t; + auto last_location_index(const ast::stmt_list::ptr& stmt, std::size_t index) -> bool; + void process_stack(const ast::decl_thread::ptr& thread); + void process_parameters(const ast::expr_parameters::ptr& params, const block::ptr& blk); + void process_stmt(const ast::stmt& stmt, const block::ptr& blk); + void process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk); + void process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk); + void process_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk); + void process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk); + void process_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk); + void process_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk); + void process_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk); + void process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk); + void process_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk); + void process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk); + void process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk); + void process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk); + void process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk); + void process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk); + void process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk); + void process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk); + void process_stmt_cases(const ast::stmt_list::ptr& stmt, const block::ptr& blk); + void process_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk); + void process_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk); + void process_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk); + void process_expr(ast::expr& expr, const block::ptr& blk); + void process_expr_assign(ast::expr_assign::ptr& expr, const block::ptr& blk); + void process_expr_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk); + void process_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk); + void process_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk); + void process_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk); + void process_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk); + void process_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk); + void process_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk); + void process_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk); + void process_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk); + void process_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk); + void process_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk); + void process_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk); + void process_expr_method_pointer(const ast::expr_pointer::ptr& expr, ast::expr& obj, const block::ptr& blk); + void process_expr_method_function(const ast::expr_function::ptr& expr, ast::expr& obj, const block::ptr& blk); + void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); + void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); + void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); + void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); + void process_var_access(ast::expr& expr, const block::ptr& blk); + void process_var_remove(const ast::asm_remove::ptr& expr, const block::ptr& blk); +}; + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/disassembler.cpp b/src/experimental/iw6c/xsk/disassembler.cpp new file mode 100644 index 00000000..a294fadb --- /dev/null +++ b/src/experimental/iw6c/xsk/disassembler.cpp @@ -0,0 +1,575 @@ +// Copyright 2022 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 "iw6c.hpp" + +namespace xsk::gsc::iw6c +{ + +auto disassembler::output() -> std::vector +{ + return std::move(functions_); +} + +auto disassembler::output_data() -> std::vector +{ + output_ = std::make_unique(0x100000); + + output_->write_string("// IW6 GSC ASSEMBLY\n"); + output_->write_string("// Disassembled by https://github.com/xensik/gsc-tool\n"); + + for (const auto& func : functions_) + { + print_function(func); + } + + std::vector output; + + output.resize(output_->pos()); + std::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()); + const auto& func = functions_.back(); + + func->index = static_cast(script_->pos()); + func->size = stack_->read_endian(); + func->id = stack_->read_endian(); + func->name = func->id == 0 ? stack_->read_c_string() : resolver::token_name(static_cast(func->id)); + + dissasemble_function(func); + + func->labels = labels_; + labels_.clear(); + } + + resolve_local_functions(); +} + +void disassembler::dissasemble_function(const function::ptr& func) +{ + auto size = func->size; + + while (size > 0) + { + func->instructions.push_back(std::make_unique()); + + const auto& inst = func->instructions.back(); + inst->index = static_cast(script_->pos()); + inst->opcode = script_->read(); + inst->size = opcode_size(inst->opcode); + + dissasemble_instruction(inst); + + size -= inst->size; + } +} + +void disassembler::dissasemble_instruction(const instruction::ptr& inst) +{ + switch (static_cast(inst->opcode)) + { + case opcode::OP_Return: + case opcode::OP_BoolNot: + case opcode::OP_CastBool: + case opcode::OP_inequality: + case opcode::OP_GetThisthread: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_checkclearparams: + case opcode::OP_CastFieldObject: + case opcode::OP_End: + case opcode::OP_size: + case opcode::OP_EmptyArray: + case opcode::OP_bit_and: + case opcode::OP_less_equal: + case opcode::OP_voidCodepos: +// case opcode::OP_ClearVariableField: + case opcode::OP_divide: + case opcode::OP_GetSelf: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_plus: + case opcode::OP_BoolComplement: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_inc: + case opcode::OP_clearparams: + case opcode::OP_EvalLocalVariableRefCached0: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_endon: + case opcode::OP_greater_equal: + case opcode::OP_GetSelfObject: + case opcode::OP_SetVariableField: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_less: + case opcode::OP_GetGameRef: + case opcode::OP_waittillFrameEnd: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_GetLevel: + case opcode::OP_notify: + case opcode::OP_DecTop: + case opcode::OP_shift_left: + case opcode::OP_greater: + 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_GetZero: + case opcode::OP_wait: + case opcode::OP_minus: +// case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_multiply: + case opcode::OP_mod: + case opcode::OP_GetGame: + case opcode::OP_waittill: + case opcode::OP_dec: + case opcode::OP_PreScriptCall: + case opcode::OP_GetAnim: + case opcode::OP_GetUndefined: + case opcode::OP_GetAnimObject: + case opcode::OP_GetLevelObject: + case opcode::OP_bit_ex_or: + case opcode::OP_equality: + case opcode::OP_ClearArray: + case opcode::OP_EvalArrayRef: + case opcode::OP_EvalArray: + case opcode::OP_vector: + case opcode::OP_bit_or: + case opcode::OP_AddArray: +// case opcode::OP_waittillmatch2: + case opcode::OP_shift_right: + 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_endian())); + break; + case opcode::OP_GetInteger: + inst->data.push_back(utils::string::va("%i", script_->read_endian())); + break; + case opcode::OP_GetFloat: + inst->data.push_back(utils::string::float_string(script_->read_endian())); + break; + case opcode::OP_GetVector: + inst->size += script_->align(4); + inst->data.push_back(utils::string::float_string(script_->read_endian())); + inst->data.push_back(utils::string::float_string(script_->read_endian())); + inst->data.push_back(utils::string::float_string(script_->read_endian())); + 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(), false)); + inst->data.push_back(utils::string::quote(stack_->read_c_string(), false)); + break; + case opcode::OP_GetAnimTree: + script_->seek(1); + inst->data.push_back(utils::string::quote(stack_->read_c_string(), 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: + 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: + disassemble_local_call(inst, false); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + disassemble_local_call(inst, true); + break; + case opcode::OP_GetFarFunction: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarMethodCall: + disassemble_far_call(inst, false); + break; + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_ScriptFarMethodChildThreadCall: + disassemble_far_call(inst, true); + break; + case opcode::OP_CallBuiltin: + disassemble_builtin_call(inst, false, true); + break; + case opcode::OP_CallBuiltinMethod: + 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: + 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: + disassemble_builtin_call(inst, true, false); + break; + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + disassemble_jump(inst, true, false); + break; + case opcode::OP_jumpback: + disassemble_jump(inst, false, true); + break; + case opcode::OP_jump: + disassemble_jump(inst, false, false); + break; + case opcode::OP_switch: + disassemble_switch(inst); + break; + case opcode::OP_endswitch: + disassemble_end_switch(inst); + break; + default: + throw disasm_error(utils::string::va("unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index)); + } +} + +void disassembler::disassemble_builtin_call(const instruction::ptr& inst, bool method, bool args) +{ + if (args) + { + inst->data.push_back(utils::string::va("%i", script_->read())); + } + + const auto id = script_->read_endian(); + const auto name = method ? resolver::method_name(id) : resolver::function_name(id); + inst->data.emplace(inst->data.begin(), name); +} + +void disassembler::disassemble_local_call(const instruction::ptr& inst, bool thread) +{ + const auto offset = 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 instruction::ptr& inst, bool thread) +{ + script_->seek(3); + + if (thread) + { + inst->data.push_back(utils::string::va("%i", script_->read())); + } + + const auto file_id = stack_->read_endian(); + const auto file_name = file_id == 0 ? stack_->read_c_string() : resolver::token_name(file_id); + const auto func_id = stack_->read_endian(); + const auto func_name = func_id == 0 ? stack_->read_c_string() : resolver::token_name(func_id); + + inst->data.emplace(inst->data.begin(), func_name); + inst->data.emplace(inst->data.begin(), file_name); +} + +void disassembler::disassemble_switch(const instruction::ptr& inst) +{ + const auto addr = inst->index + 4 + script_->read_endian(); + const auto label = utils::string::va("loc_%X", addr); + + inst->data.push_back(label); + labels_.insert({ addr, label }); +} + +void disassembler::disassemble_end_switch(const instruction::ptr& inst) +{ + const auto count = script_->read_endian(); + inst->data.push_back(utils::string::va("%i", count)); + + std::uint32_t index = inst->index + 3; + + if (count) + { + for (auto i = count; i > 0; i--) + { + const auto value = script_->read_endian(); + + if (value < 0x40000) + { + const auto data = stack_->read_c_string(); + + if (data.data()[0] != 0x01) + { + inst->data.push_back("case"); + inst->data.push_back(utils::string::quote(data, false)); + } + else + inst->data.push_back("default"); + } + else + { + inst->data.push_back("case"); + inst->data.push_back(utils::string::va("%i", (value - 0x800000) & 0xFFFFFF)); + } + + index += 4; + + const auto addr = disassemble_offset() + index; + const auto label = utils::string::va("loc_%X", addr); + + inst->data.push_back(label); + labels_.insert({ addr, label }); + + index += 3; + inst->size += 7; + } + } +} + +void disassembler::disassemble_field_variable(const instruction::ptr& inst) +{ + const auto id = script_->read_endian(); + std::string name; + + if (id > max_string_id) + { + auto temp = stack_->read_endian(); + name = temp == 0 ? stack_->read_c_string() : std::to_string(temp); + } + else + { + name = resolver::token_name(id); + } + + inst->data.push_back(name); +} + +void disassembler::disassemble_jump(const instruction::ptr& inst, bool expr, bool back) +{ + std::int32_t addr; + + if (expr) + { + addr = inst->index + 3 + script_->read_endian(); + } + else if (back) + { + addr = inst->index + 3 - script_->read_endian(); + } + else + { + addr = inst->index + 5 + script_->read_endian(); + } + + const auto label = utils::string::va("loc_%X", addr); + + inst->data.push_back(label); + labels_.insert({ addr, label }); +} + +auto disassembler::disassemble_offset() -> std::int32_t +{ + std::array bytes = {}; + + for (auto i = 0; i < 3; i++) + { + bytes[2 - i] = script_->read(); + } + + auto offset = *reinterpret_cast(bytes.data()); + + offset = (offset << 8) >> 10; + + return offset; +} + +void disassembler::resolve_local_functions() +{ + for (const auto& func : functions_) + { + for (const auto& inst : func->instructions) + { + switch (static_cast(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[0] = 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 (const auto& func : functions_) + { + if (func->index == idx) + { + return func->name; + } + } + + throw disasm_error(utils::string::va("couldn't resolve function name at index '0x%04X'!", idx)); + } + + throw disasm_error(utils::string::va("\"%s\" is not valid function address!", index.data())); +} + +void disassembler::print_function(const function::ptr& func) +{ + output_->write_string("\n"); + output_->write_string(utils::string::va("sub_%s\n", func->name.data())); + + for (const 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())); + } + + print_instruction(inst); + } + + output_->write_string(utils::string::va("end_%s\n", func->name.data())); +} + +void disassembler::print_instruction(const instruction::ptr& inst) +{ + output_->write_string(utils::string::va("\t\t%s", resolver::opcode_name(inst->opcode).data())); + + switch (static_cast(inst->opcode)) + { + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalMethodCall: + output_->write_string(utils::string::va(" sub_%s", inst->data[0].data())); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + output_->write_string(utils::string::va(" sub_%s %s\n", inst->data[0].data(), inst->data[1].data())); + break; + case opcode::OP_endswitch: + 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: + for (auto& data : inst->data) + { + output_->write_string(utils::string::va(" %s", data.data())); + } + break; + } + + output_->write_string("\n"); +} + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/disassembler.hpp b/src/experimental/iw6c/xsk/disassembler.hpp new file mode 100644 index 00000000..00abe1ea --- /dev/null +++ b/src/experimental/iw6c/xsk/disassembler.hpp @@ -0,0 +1,42 @@ +// Copyright 2022 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::iw6c +{ + +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 function::ptr& func); + void dissasemble_instruction(const instruction::ptr& inst); + void disassemble_builtin_call(const instruction::ptr& inst, bool method, bool args); + void disassemble_local_call(const instruction::ptr& inst, bool thread); + void disassemble_far_call(const instruction::ptr& inst, bool thread); + void disassemble_switch(const instruction::ptr& inst); + void disassemble_end_switch(const instruction::ptr& inst); + void disassemble_field_variable(const instruction::ptr& inst); + void disassemble_jump(const instruction::ptr& inst, bool expr, bool back); + auto disassemble_offset() -> std::int32_t; + void resolve_local_functions(); + auto resolve_function(const std::string& index) -> std::string; + void print_function(const function::ptr& func); + void print_instruction(const instruction::ptr& inst); +}; + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/iw6c.cpp b/src/experimental/iw6c/xsk/iw6c.cpp new file mode 100644 index 00000000..2e5ce897 --- /dev/null +++ b/src/experimental/iw6c/xsk/iw6c.cpp @@ -0,0 +1,179 @@ +// Copyright 2022 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 "iw6c.hpp" + +namespace xsk::gsc::iw6c +{ + +auto opcode_size(std::uint8_t id) -> std::uint32_t +{ + switch (static_cast(id)) + { + case opcode::OP_End: + case opcode::OP_Return: + case opcode::OP_GetUndefined: + case opcode::OP_GetZero: + case opcode::OP_waittillFrameEnd: + 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_EvalArray: + case opcode::OP_EvalArrayRef: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_ClearArray: + case opcode::OP_EmptyArray: + case opcode::OP_AddArray: + case opcode::OP_PreScriptCall: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_GetLevelObject: + case opcode::OP_GetAnimObject: + case opcode::OP_GetSelf: + case opcode::OP_GetThisthread: + case opcode::OP_GetLevel: + case opcode::OP_GetGame: + case opcode::OP_GetAnim: + case opcode::OP_GetGameRef: + case opcode::OP_inc: + case opcode::OP_dec: + case opcode::OP_bit_or: + case opcode::OP_bit_ex_or: + case opcode::OP_bit_and: + case opcode::OP_equality: + case opcode::OP_inequality: + case opcode::OP_less: + case opcode::OP_greater: + case opcode::OP_less_equal: + // case opcode::OP_waittillmatch2: + case opcode::OP_waittill: + case opcode::OP_notify: + case opcode::OP_endon: + case opcode::OP_voidCodepos: + case opcode::OP_vector: + case opcode::OP_greater_equal: + case opcode::OP_shift_left: + case opcode::OP_shift_right: + case opcode::OP_plus: + case opcode::OP_minus: + case opcode::OP_multiply: + case opcode::OP_divide: + case opcode::OP_mod: + case opcode::OP_size: + case opcode::OP_GetSelfObject: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_clearparams: + case opcode::OP_checkclearparams: + case opcode::OP_EvalLocalVariableRefCached0: + // case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_SetVariableField: + // case opcode::OP_ClearVariableField: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_wait: + case opcode::OP_DecTop: + case opcode::OP_CastFieldObject: + case opcode::OP_CastBool: + case opcode::OP_BoolNot: + case opcode::OP_BoolComplement: + return 1; + case opcode::OP_GetByte: + case opcode::OP_GetNegByte: + case opcode::OP_CreateLocalVariable: + case opcode::OP_RemoveLocalVariables: + case opcode::OP_EvalLocalVariableCached: + case opcode::OP_EvalLocalArrayCached: + case opcode::OP_EvalNewLocalArrayRefCached0: + case opcode::OP_EvalLocalArrayRefCached: + case opcode::OP_ScriptThreadCallPointer: + case opcode::OP_ScriptMethodThreadCallPointer: + case opcode::OP_ScriptMethodChildThreadCallPointer: + case opcode::OP_CallBuiltinPointer: + case opcode::OP_CallBuiltinMethodPointer: + case opcode::OP_SafeCreateVariableFieldCached: + case opcode::OP_SafeSetVariableFieldCached: + case opcode::OP_SafeSetWaittillVariableFieldCached: + case opcode::OP_GetAnimTree: + case opcode::OP_EvalLocalVariableRefCached: + case opcode::OP_SetNewLocalVariableFieldCached0: + case opcode::OP_SetLocalVariableFieldCached: + case opcode::OP_ClearLocalVariableFieldCached: + case opcode::OP_EvalLocalVariableObjectCached: + return 2; + case opcode::OP_GetUnsignedShort: + case opcode::OP_GetNegUnsignedShort: + case opcode::OP_GetBuiltinFunction: + case opcode::OP_GetBuiltinMethod: + case opcode::OP_GetString: + case opcode::OP_GetIString: + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + case opcode::OP_jumpback: + case opcode::OP_endswitch: + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + case opcode::OP_waittillmatch: + case opcode::OP_EvalLevelFieldVariable: + case opcode::OP_EvalAnimFieldVariable: + case opcode::OP_EvalSelfFieldVariable: + case opcode::OP_EvalFieldVariable: + case opcode::OP_EvalLevelFieldVariableRef: + case opcode::OP_EvalAnimFieldVariableRef: + case opcode::OP_EvalSelfFieldVariableRef: + case opcode::OP_EvalFieldVariableRef: + case opcode::OP_ClearFieldVariable: + case opcode::OP_SetLevelFieldVariableField: + case opcode::OP_SetAnimFieldVariableField: + case opcode::OP_SetSelfFieldVariableField: + 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_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_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalMethodCall: + case opcode::OP_GetLocalFunction: + case opcode::OP_CallBuiltin: + case opcode::OP_CallBuiltinMethod: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarMethodCall: + case opcode::OP_GetFarFunction: + return 4; + case opcode::OP_GetInteger: + case opcode::OP_GetFloat: + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_ScriptFarMethodChildThreadCall: + case opcode::OP_GetAnimation: + case opcode::OP_switch: + case opcode::OP_jump: + return 5; + case opcode::OP_GetVector: + return 13; + default: + throw error("couldn't resolve instruction size for " + std::to_string(id)); + } +} + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6_console/xsk/iw6_console.hpp b/src/experimental/iw6c/xsk/iw6c.hpp similarity index 94% rename from src/experimental/iw6_console/xsk/iw6_console.hpp rename to src/experimental/iw6c/xsk/iw6c.hpp index f9f90a5d..e716167d 100644 --- a/src/experimental/iw6_console/xsk/iw6_console.hpp +++ b/src/experimental/iw6c/xsk/iw6c.hpp @@ -7,9 +7,18 @@ #include "utils/xsk/utils.hpp" -namespace xsk::gsc::iw6_console +#include "assembler.hpp" +#include "disassembler.hpp" +#include "compiler.hpp" +#include "decompiler.hpp" +#include "resolver.hpp" +#include "context.hpp" + +namespace xsk::gsc::iw6c { +constexpr std::uint16_t max_string_id = 0x0; + enum class opcode : std::uint8_t { OP_CastFieldObject = 0x1D, @@ -32,7 +41,7 @@ enum class opcode : std::uint8_t OP_ClearLocalVariableFieldCached0 = 0x2E, OP_notify = 0x2F, OP_GetVector = 0x30, - OP_ScriptMethodChildThreadCallPointer = 0x31, + OP_ScriptChildThreadCallPointer = 0x31, OP_voidCodepos = 0x32, OP_GetByte = 0x33, OP_ScriptFarMethodThreadCall = 0x34, @@ -169,4 +178,4 @@ enum class opcode : std::uint8_t auto opcode_size(std::uint8_t id) -> std::uint32_t; -} // namespace xsk::gsc::iw6_console +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/lexer.cpp b/src/experimental/iw6c/xsk/lexer.cpp new file mode 100644 index 00000000..7f001c8f --- /dev/null +++ b/src/experimental/iw6c/xsk/lexer.cpp @@ -0,0 +1,848 @@ +// Copyright 2022 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 "iw6c.hpp" +#include "parser.hpp" +#include "lexer.hpp" + +xsk::gsc::iw6c::parser::symbol_type IW6Clex(xsk::gsc::iw6c::lexer& lexer) +{ + return lexer.lex(); +} + +namespace xsk::gsc::iw6c +{ + +const std::unordered_map keyword_map +{{ + { "#define", parser::token::SH_DEFINE }, + { "#undef", parser::token::SH_UNDEF }, + { "#ifdef", parser::token::SH_IFDEF }, + { "#ifndef", parser::token::SH_IFNDEF }, + { "#if", parser::token::SH_IF }, + { "#elif", parser::token::SH_ELIF }, + { "#else", parser::token::SH_ELSE }, + { "#endif", parser::token::SH_ENDIF }, + { "#inline", parser::token::INLINE }, + { "#include", parser::token::INCLUDE }, + { "#using_animtree", parser::token::USINGTREE }, + { "#animtree", parser::token::ANIMTREE }, + { "endon", parser::token::ENDON }, + { "notify", parser::token::NOTIFY }, + { "wait", parser::token::WAIT }, + { "waittill", parser::token::WAITTILL }, + { "waittillmatch", parser::token::WAITTILLMATCH }, + { "waittillframeend", parser::token::WAITTILLFRAMEEND }, + { "if", parser::token::IF }, + { "else", parser::token::ELSE }, + { "do", parser::token::DO }, + { "while", parser::token::WHILE }, + { "for", parser::token::FOR }, + { "foreach", parser::token::FOREACH }, + { "in", parser::token::IN }, + { "switch", parser::token::SWITCH }, + { "case", parser::token::CASE }, + { "default", parser::token::DEFAULT }, + { "break", parser::token::BREAK }, + { "continue", parser::token::CONTINUE }, + { "return", parser::token::RETURN }, + { "breakpoint", parser::token::BREAKPOINT }, + { "prof_begin", parser::token::PROFBEGIN }, + { "prof_end", parser::token::PROFEND }, + { "thread", parser::token::THREAD }, + { "childthread", parser::token::CHILDTHREAD }, + { "thisthread", parser::token::THISTHREAD }, + { "call", parser::token::CALL }, + { "true", parser::token::TRUE }, + { "false", parser::token::FALSE }, + { "undefined", parser::token::UNDEFINED }, + { "size", parser::token::SIZE }, + { "game", parser::token::GAME }, + { "self", parser::token::SELF }, + { "anim", parser::token::ANIM }, + { "level", parser::token::LEVEL }, +}}; + +buffer::buffer() : length(0) +{ + data = static_cast(std::malloc(max_buf_size)); +} + +buffer::~buffer() +{ + if (data) std::free(data); +} + +bool buffer::push(char c) +{ + if (length >= max_buf_size) + return false; + + data[length++] = c; + return true; +} + +reader::reader() : buffer_pos(0), bytes_remaining(0), last_byte(0), current_byte(0), state(reader::end) +{ + +} + +void reader::init(const char* data, size_t size) +{ + if (data && size) + { + state = reader::ok; + buffer_pos = data; + bytes_remaining = static_cast(size); + last_byte = 0; + current_byte = *data; + } + else + { + state = reader::end; + buffer_pos = 0; + bytes_remaining = 0; + last_byte = 0; + current_byte = 0; + } +} + +void reader::advance() +{ + ++buffer_pos; + + if (bytes_remaining-- == 1) + { + state = reader::end; + bytes_remaining = 0; + last_byte = current_byte; + current_byte = 0; + } + else + { + last_byte = current_byte; + current_byte = *buffer_pos; + } +} + +lexer::lexer(build mode, const std::string& name, const char* data, size_t size) : loc_(location(&name)), + locs_(std::stack()), readers_(std::stack()), header_top_(0), mode_(mode), indev_(false), clean_(true) +{ + reader_.init(data, size); +} + +void lexer::push_header(const std::string& file) +{ + try + { + if (header_top_++ >= 10) + throw comp_error(loc_, "maximum gsh depth exceeded '10'"); + + auto data = resolver::file_data(file + ".gsh"); + + readers_.push(reader_); + locs_.push(loc_); + loc_.initialize(std::get<0>(data)); + reader_.init(std::get<1>(data), std::get<2>(data)); + clean_ = true; + } + catch (const std::exception& e) + { + throw error("parsing header file '" + file + "': " + e.what()); + } +} + +void lexer::pop_header() +{ + header_top_--; + loc_ = locs_.top(); + locs_.pop(); + reader_ = readers_.top(); + readers_.pop(); +} + +void lexer::ban_header(const location& loc) +{ + if (header_top_ > 0) + { + throw comp_error(loc, "not allowed inside a gsh file"); + } +} + +auto lexer::lex() -> parser::symbol_type +{ + buffer_.length = 0; + state_ = state::start; + + while (true) + { + const auto& state = reader_.state; + auto& last = reader_.last_byte; + auto& curr = reader_.current_byte; + auto path = false; + loc_.step(); + + if (state == reader::end) + { + if (indev_) + throw comp_error(loc_, "unmatched devblock start ('/#')"); + + if (header_top_ > 0) + pop_header(); + else + return parser::make_IW6CEOF(loc_); + } + + if (clean_ && last != 0 && last != ' ' && last != '\t' && last != '\n') + clean_ = false; + + advance(); + + switch (last) + { + case ' ': + case '\t': + case '\r': + loc_.step(); + continue; + case '\n': + loc_.lines(); + loc_.step(); + clean_ = true; + continue; + case '\\': + throw comp_error(loc_, "invalid token ('\\')"); + case '/': + if (curr != '=' && curr != '#' && curr != '@' && curr != '*' && curr != '/') + return parser::make_DIV(loc_); + + advance(); + + if (last == '=') + return parser::make_ASSIGN_DIV(loc_); + + if (last == '#') + { + if (indev_) + throw comp_error(loc_, "cannot recurse devblock ('/#')"); + + if (mode_ == build::dev) + { + indev_ = true; + return parser::make_DEVBEGIN(loc_); + } + else + { + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched devblock start ('/#')"); + + if (curr == '\n') + { + loc_.lines(); + loc_.step(); + } + else if (last == '#' && curr == '/') + { + advance(); + break; + } + + advance(); + } + } + } + else if (last == '@') + { + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched script doc comment start ('/@')"); + + if (curr == '\n') + { + loc_.lines(); + loc_.step(); + } + else if (last == '@' && curr == '/') + { + advance(); + break; + } + + advance(); + } + } + else if (last == '*') + { + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched multiline comment start ('/*')"); + + if (curr == '\n') + { + loc_.lines(); + loc_.step(); + } + else if (last == '*' && curr == '/') + { + advance(); + break; + } + + advance(); + } + } + else if (last == '/') + { + while (true) + { + if (state == reader::end) + break; + + if (curr == '\n') + break; + + advance(); + } + } + continue; + case '#': + if (curr == '/') + { + if (!indev_) + throw comp_error(loc_, "unmatched devblock end ('#/')"); + + advance(); + indev_ = false; + return parser::make_DEVEND(loc_); + } + + buffer_.push(last); + advance(); + + while (state == reader::ok) + { + if (last != ' ' || last != '\t') + break; + + advance(); + } + + if (state == reader::end || !((last > 64 && last < 91) || (last > 96 && last < 123))) + throw comp_error(loc_, "invalid preprocessor directive ('#')"); + + state_ = state::preprocessor; + goto lex_name; + case '*': + if (curr != '=' && curr != '/') + return parser::make_MUL(loc_); + + advance(); + + if (last == '=') + return parser::make_ASSIGN_MUL(loc_); + + throw comp_error(loc_, "unmatched multiline comment end ('*/')"); + case '"': + state_ = state::string; + goto lex_string; + case '.': + if (curr < '0' || curr > '9') + return parser::make_DOT(loc_); + goto lex_number; + case '(': + return parser::make_LPAREN(loc_); + case ')': + return parser::make_RPAREN(loc_); + case '{': + return parser::make_LBRACE(loc_); + case '}': + return parser::make_RBRACE(loc_); + case '[': + return parser::make_LBRACKET(loc_); + case ']': + return parser::make_RBRACKET(loc_); + case ',': + return parser::make_COMMA(loc_); + case ';': + return parser::make_SEMICOLON(loc_); + case ':': + if (curr != ':') + return parser::make_COLON(loc_); + + advance(); + return parser::make_DOUBLECOLON(loc_); + case '?': + return parser::make_QMARK(loc_); + case '=': + if (curr != '=') + return parser::make_ASSIGN(loc_); + + advance(); + return parser::make_EQUALITY(loc_); + case '+': + if (curr != '+' && curr != '=') + return parser::make_ADD(loc_); + + advance(); + + if (last == '+') + return parser::make_INCREMENT(loc_); + + return parser::make_ASSIGN_ADD(loc_); + case '-': + if (curr != '-' && curr != '=') + return parser::make_SUB(loc_); + + advance(); + + if (last == '-') + return parser::make_DECREMENT(loc_); + + return parser::make_ASSIGN_SUB(loc_); + case '%': + if (curr != '=') + return parser::make_MOD(loc_); + + advance(); + + return parser::make_ASSIGN_MOD(loc_); + case '|': + if (curr != '|' && curr != '=') + return parser::make_BITWISE_OR(loc_); + + advance(); + + if (last == '|') + return parser::make_OR(loc_); + + return parser::make_ASSIGN_BW_OR(loc_); + case '&': + if (curr != '&' && curr != '=' && curr != '"') + return parser::make_BITWISE_AND(loc_); + + advance(); + + if (last == '&') + return parser::make_AND(loc_); + + if (last == '=') + return parser::make_ASSIGN_BW_AND(loc_); + + state_ = state::localize; + goto lex_string; + case '^': + if (curr != '=') + return parser::make_BITWISE_EXOR(loc_); + + advance(); + return parser::make_ASSIGN_BW_EXOR(loc_); + case '!': + if (curr != '=') + return parser::make_NOT(loc_); + + advance(); + return parser::make_INEQUALITY(loc_); + case '~': + return parser::make_COMPLEMENT(loc_); + case '<': + if (curr != '<' && curr != '=') + return parser::make_LESS(loc_); + + advance(); + if (last == '=') + return parser::make_LESS_EQUAL(loc_); + + if (curr != '=') + return parser::make_LSHIFT(loc_); + + advance(); + return parser::make_ASSIGN_LSHIFT(loc_); + case '>': + if (curr != '>' && curr != '=') + return parser::make_GREATER(loc_); + + advance(); + + if (last == '=') + return parser::make_GREATER_EQUAL(loc_); + + if (curr != '=') + return parser::make_RSHIFT(loc_); + + advance(); + return parser::make_ASSIGN_RSHIFT(loc_); + default: + if (last >= '0' && last <= '9') + goto lex_number; + else if (last == '_' || (last >= 'A' && last <= 'Z') || (last >= 'a' && last <= 'z')) + goto lex_name; + + throw comp_error(loc_, utils::string::va("bad token: \'%c\'", last)); + } + +lex_string: + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched string start ('\"')"); + + if (curr == '"') + { + advance(); + break; + } + + if (curr == '\n') + throw comp_error(loc_, "unterminated string literal"); + + if (curr == '\\') + { + advance(); + + if (state == reader::end) + throw comp_error(loc_, "invalid token ('\')"); + + char c = curr; + switch (curr) + { + case 't': c = '\t'; break; + case 'r': c = '\r'; break; + case 'n': c = '\n'; break; + case '"': c = '\"'; break; + case '\\': c = '\\'; break; + default: break; + } + + if (!buffer_.push(c)) + throw comp_error(loc_, "max string size exceeded"); + } + else if (!buffer_.push(curr)) + throw comp_error(loc_, "max string size exceeded"); + + advance(); + } + + if (state_ == state::localize) + return parser::make_ISTRING(std::string(buffer_.data, buffer_.length), loc_); + + return parser::make_STRING(std::string(buffer_.data, buffer_.length), loc_); + +lex_name: + buffer_.push(last); + + while (true) + { + if (state == reader::end) + break; + + if (!(curr == '\\' || curr == '_' || (curr > 64 && curr < 91) || (curr > 96 && curr < 123) || (curr > 47 && curr < 58))) + break; + + if (curr == '\\') + { + if (last == '\\') + throw comp_error(loc_, "invalid path '\\\\'"); + + path = true; + if (!buffer_.push('/')) + throw comp_error(loc_, "max string size exceeded"); + } + else if (!buffer_.push(curr)) + throw comp_error(loc_, "max string size exceeded"); + + advance(); + } + + if (state_ == state::preprocessor) + { + auto token = parser::token::IW6CUNDEF; + + if (buffer_.length < 16) + { + const auto itr = keyword_map.find(std::string_view(buffer_.data, buffer_.length)); + + if (itr != keyword_map.end()) + { + if (itr->second > parser::token::SH_ENDIF) + return parser::symbol_type(itr->second, loc_); + + token = itr->second; + } + } + + preprocessor_run(token); + + state_ = state::start; + continue; + } + else + { + if (buffer_.length < 17) + { + const auto itr = keyword_map.find(std::string_view(buffer_.data, buffer_.length)); + + if (itr != keyword_map.end()) + return parser::symbol_type(itr->second, loc_); + } + + if (path) + { + if (buffer_.data[buffer_.length - 1] == '/') + throw comp_error(loc_, "invalid path end '\\'"); + + return parser::make_PATH(resolver::make_token(std::string_view(buffer_.data, buffer_.length)), loc_); + } + + return parser::make_IDENTIFIER(resolver::make_token(std::string_view(buffer_.data, buffer_.length)), loc_); + } + +lex_number: + if (last == '.' || last != '0' || (last == '0' && (curr != 'o' && curr != 'b' && curr != 'x'))) + { + buffer_.push(last); + + auto dot = last == '.' ? 1 : 0; + auto flt = 0; + + while (true) + { + if (state == reader::end) + break; + + if (curr == '\'' && (last == '\'' || last == 'f' || last == '.')) + throw comp_error(loc_, "invalid number literal"); + + if ((curr == '.' || curr == 'f') && last == '\'') + throw comp_error(loc_, "invalid number literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (curr == 'f') + flt++; + else if (curr == '.') + dot++; + else if (!(curr > 47 && curr < 58)) + break; + + if (!buffer_.push(curr)) + throw comp_error(loc_, "number literal size exceeded"); + + advance(); + } + + if (last == '\'') + throw comp_error(loc_, "invalid number literal"); + + if (dot > 1 || flt > 1 || (flt && buffer_.data[buffer_.length - 1] != 'f')) + throw comp_error(loc_, "invalid number literal"); + + if (dot || flt) + return parser::make_FLOAT(std::string(buffer_.data, buffer_.length), loc_); + + return parser::make_INTEGER(std::string(buffer_.data, buffer_.length), loc_); + } + else if (curr == 'o') + { + advance(); + + while (true) + { + if (state == reader::end) + break; + + if ((curr == '\'' && (last == '\'' || last == 'o')) || (curr == 'o' && last == '\'')) + throw comp_error(loc_, "invalid octal literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (!(curr > 47 && curr < 56)) + break; + + if (!buffer_.push(curr)) + throw error("gsc lexer: out of memory!"); + + advance(); + } + + if (last == '\'' || buffer_.length <= 0) + throw comp_error(loc_, "invalid octal literal"); + + return parser::make_INTEGER(utils::string::oct_to_dec(buffer_.data), loc_); + } + else if (curr == 'b') + { + buffer_.push(last); + buffer_.push(curr); + advance(); + + while (true) + { + if (state == reader::end) + break; + + if ((curr == '\'' && (last == '\'' || last == 'b')) || (curr == 'b' && last == '\'')) + throw comp_error(loc_, "invalid binary literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (curr != '0' && curr != '1') + break; + + if (!buffer_.push(curr)) + throw comp_error(loc_, "number literal size exceeded"); + + advance(); + } + + if (last == '\'' || buffer_.length < 3) + throw comp_error(loc_, "invalid binary literal"); + + return parser::make_INTEGER(utils::string::bin_to_dec(buffer_.data), loc_); + } + else if (curr == 'x') + { + buffer_.push(last); + buffer_.push(curr); + advance(); + + while (true) + { + if (state == reader::end) + break; + + if ((curr == '\'' && (last == '\'' || last == 'x')) || (curr == 'x' && last == '\'')) + throw comp_error(loc_, "invalid hexadecimal literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (!((curr > 47 && curr < 58) || (curr > 64 && curr < 71) || (curr > 96 && curr < 103))) + break; + + if (!buffer_.push(curr)) + throw error("gsc lexer: out of memory!"); + + advance(); + } + + if (last == '\'' || buffer_.length < 3) + throw comp_error(loc_, "invalid hexadecimal literal"); + + return parser::make_INTEGER(utils::string::hex_to_dec(buffer_.data), loc_); + } + + throw error("UNEXPECTED LEXER INTERNAL ERROR!"); + } +} + +void lexer::advance() +{ + reader_.advance(); + loc_.end.column++; + + if (reader_.current_byte == '\\') [[unlikely]] + preprocessor_wrap(); +} + +void lexer::preprocessor_wrap() +{ + while (reader_.current_byte == '\\') + { + if (reader_.bytes_remaining == 1) + throw comp_error(loc_, "invalid token ('\\')"); + + if (reader_.buffer_pos[1] != '\r' && reader_.buffer_pos[1] != '\n') + break; + + if (reader_.buffer_pos[1] == '\r') + { + if (reader_.bytes_remaining <= 3 || reader_.buffer_pos[2] != '\n') + throw comp_error(loc_, "invalid token ('\\')"); + + reader_.buffer_pos += 3; + reader_.bytes_remaining -= 3; + } + + if ((reader_.buffer_pos[1] == '\n')) + { + if (reader_.bytes_remaining == 2) + throw comp_error(loc_, "invalid token ('\\')"); + + reader_.buffer_pos += 2; + reader_.bytes_remaining -= 2; + } + + if (reader_.bytes_remaining == 0) + { + reader_.state = reader::end; + reader_.current_byte = 0; + } + else + { + reader_.current_byte = *reader_.buffer_pos; + } + + loc_.lines(); + loc_.step(); + } +} + +void lexer::preprocessor_run(parser::token::token_kind_type token) +{ + if (!clean_) + throw comp_error(loc_, "invalid token ('#')"); + + switch (token) + { + case parser::token::SH_DEFINE: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_UNDEF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_IFDEF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_IFNDEF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_IF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_ELIF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_ELSE: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_ENDIF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + default: + throw comp_error(loc_, "unknown preprocessor directive"); + } +} + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/lexer.hpp b/src/experimental/iw6c/xsk/lexer.hpp new file mode 100644 index 00000000..150ff34f --- /dev/null +++ b/src/experimental/iw6c/xsk/lexer.hpp @@ -0,0 +1,78 @@ +// Copyright 2022 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::iw6c +{ + +constexpr size_t max_buf_size = 0x2000; + +struct buffer +{ + char* data; + size_t length; + + buffer(); + ~buffer(); + bool push(char c); +}; + +struct reader +{ + enum state_type : std::uint8_t { end, ok }; + + const char* buffer_pos; + std::uint32_t bytes_remaining; + char last_byte; + char current_byte; + state_type state; + + reader(); + + reader(const reader& obj) + { + std::memcpy(this, &obj, sizeof(reader)); + } + + reader& operator=(const reader& obj) + { + std::memcpy(this, &obj, sizeof(reader)); + return *this; + } + + void init(const char* data, size_t size); + void advance(); +}; + +class lexer +{ + enum class state : std::uint8_t { start, string, localize, preprocessor }; + + reader reader_; + buffer buffer_; + location loc_; + std::stack locs_; + std::stack readers_; + std::uint32_t header_top_; + state state_; + build mode_; + bool indev_; + bool clean_; + +public: + lexer(build mode, const std::string& name, const char* data, size_t size); + auto lex() -> parser::symbol_type; + void push_header(const std::string& file); + void pop_header(); + void ban_header(const location& loc); + +private: + void advance(); + void preprocessor_wrap(); + void preprocessor_run(parser::token::token_kind_type token); +}; + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/iw6c/xsk/parser.cpp b/src/experimental/iw6c/xsk/parser.cpp new file mode 100644 index 00000000..eb786361 --- /dev/null +++ b/src/experimental/iw6c/xsk/parser.cpp @@ -0,0 +1,4668 @@ +// A Bison parser, made by GNU Bison 3.8.2. + +// 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 38 "parser.ypp" + +#include "stdafx.hpp" +#include "parser.hpp" +#include "lexer.hpp" +using namespace xsk::gsc; +xsk::gsc::iw6c::parser::symbol_type IW6Clex(xsk::gsc::iw6c::lexer& lexer); + +#line 47 "parser.cpp" + +// Take the name prefix into account. +#define yylex IW6Clex + + + +#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 IW6CDEBUG + +// 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 // !IW6CDEBUG + +# 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 // !IW6CDEBUG + +#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 iw6c { +#line 149 "parser.cpp" + + /// Build a parser object. + parser::parser (xsk::gsc::iw6c::lexer& lexer_yyarg, xsk::gsc::ast::program::ptr& ast_yyarg) +#if IW6CDEBUG + : yydebug_ (false), + yycdebug_ (&std::cerr), +#else + : +#endif + yy_lac_established_ (false), + lexer (lexer_yyarg), + ast (ast_yyarg) + {} + + parser::~parser () + {} + + parser::syntax_error::~syntax_error () YY_NOEXCEPT YY_NOTHROW + {} + + /*---------. + | symbol. | + `---------*/ + + + + // 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.YY_MOVE_OR_COPY< ast::call > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.YY_MOVE_OR_COPY< ast::decl > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.YY_MOVE_OR_COPY< ast::decl_constant::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.YY_MOVE_OR_COPY< ast::decl_thread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.YY_MOVE_OR_COPY< ast::decl_usingtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.YY_MOVE_OR_COPY< ast::expr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.YY_MOVE_OR_COPY< ast::expr_add_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.YY_MOVE_OR_COPY< ast::expr_anim::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.YY_MOVE_OR_COPY< ast::expr_animation::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.YY_MOVE_OR_COPY< ast::expr_animtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.YY_MOVE_OR_COPY< ast::expr_arguments::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.YY_MOVE_OR_COPY< ast::expr_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.YY_MOVE_OR_COPY< ast::expr_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.YY_MOVE_OR_COPY< ast::expr_complement::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.YY_MOVE_OR_COPY< ast::expr_empty_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.YY_MOVE_OR_COPY< ast::expr_false::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.YY_MOVE_OR_COPY< ast::expr_field::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.YY_MOVE_OR_COPY< ast::expr_float::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.YY_MOVE_OR_COPY< ast::expr_game::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.YY_MOVE_OR_COPY< ast::expr_identifier::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.YY_MOVE_OR_COPY< ast::expr_integer::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.YY_MOVE_OR_COPY< ast::expr_istring::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.YY_MOVE_OR_COPY< ast::expr_level::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.YY_MOVE_OR_COPY< ast::expr_method::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.YY_MOVE_OR_COPY< ast::expr_negate::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.YY_MOVE_OR_COPY< ast::expr_not::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.YY_MOVE_OR_COPY< ast::expr_parameters::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.YY_MOVE_OR_COPY< ast::expr_paren::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.YY_MOVE_OR_COPY< ast::expr_path::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.YY_MOVE_OR_COPY< ast::expr_reference::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.YY_MOVE_OR_COPY< ast::expr_self::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.YY_MOVE_OR_COPY< ast::expr_size::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.YY_MOVE_OR_COPY< ast::expr_string::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.YY_MOVE_OR_COPY< ast::expr_thisthread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.YY_MOVE_OR_COPY< ast::expr_true::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.YY_MOVE_OR_COPY< ast::expr_tuple::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.YY_MOVE_OR_COPY< ast::expr_undefined::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.YY_MOVE_OR_COPY< ast::expr_vector::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.YY_MOVE_OR_COPY< ast::include::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.YY_MOVE_OR_COPY< ast::program::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.YY_MOVE_OR_COPY< ast::stmt > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.YY_MOVE_OR_COPY< ast::stmt_assign::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.YY_MOVE_OR_COPY< ast::stmt_break::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.YY_MOVE_OR_COPY< ast::stmt_breakpoint::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.YY_MOVE_OR_COPY< ast::stmt_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.YY_MOVE_OR_COPY< ast::stmt_case::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.YY_MOVE_OR_COPY< ast::stmt_continue::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.YY_MOVE_OR_COPY< ast::stmt_default::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.YY_MOVE_OR_COPY< ast::stmt_dev::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.YY_MOVE_OR_COPY< ast::stmt_dowhile::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.YY_MOVE_OR_COPY< ast::stmt_endon::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.YY_MOVE_OR_COPY< ast::stmt_expr::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.YY_MOVE_OR_COPY< ast::stmt_for::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.YY_MOVE_OR_COPY< ast::stmt_foreach::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.YY_MOVE_OR_COPY< ast::stmt_if::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.YY_MOVE_OR_COPY< ast::stmt_ifelse::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.YY_MOVE_OR_COPY< ast::stmt_list::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.YY_MOVE_OR_COPY< ast::stmt_notify::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.YY_MOVE_OR_COPY< ast::stmt_prof_begin::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.YY_MOVE_OR_COPY< ast::stmt_prof_end::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.YY_MOVE_OR_COPY< ast::stmt_return::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.YY_MOVE_OR_COPY< ast::stmt_switch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.YY_MOVE_OR_COPY< ast::stmt_wait::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.YY_MOVE_OR_COPY< ast::stmt_waittill::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.YY_MOVE_OR_COPY< ast::stmt_waittillframeend::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.YY_MOVE_OR_COPY< ast::stmt_waittillmatch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.YY_MOVE_OR_COPY< ast::stmt_while::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.YY_MOVE_OR_COPY< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.copy< ast::call > (that.value); + break; + + case symbol_kind::S_declaration: // declaration + value.copy< ast::decl > (that.value); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.copy< ast::decl_constant::ptr > (that.value); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.copy< ast::decl_thread::ptr > (that.value); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.copy< ast::decl_usingtree::ptr > (that.value); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.copy< ast::expr > (that.value); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.copy< ast::expr_add_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.copy< ast::expr_anim::ptr > (that.value); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.copy< ast::expr_animation::ptr > (that.value); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.copy< ast::expr_animtree::ptr > (that.value); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.copy< ast::expr_arguments::ptr > (that.value); + break; + + case symbol_kind::S_expr_array: // expr_array + value.copy< ast::expr_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_call: // expr_call + value.copy< ast::expr_call::ptr > (that.value); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.copy< ast::expr_complement::ptr > (that.value); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.copy< ast::expr_empty_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_false: // expr_false + value.copy< ast::expr_false::ptr > (that.value); + break; + + case symbol_kind::S_expr_field: // expr_field + value.copy< ast::expr_field::ptr > (that.value); + break; + + case symbol_kind::S_expr_float: // expr_float + value.copy< ast::expr_float::ptr > (that.value); + break; + + case symbol_kind::S_expr_game: // expr_game + value.copy< ast::expr_game::ptr > (that.value); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.copy< ast::expr_identifier::ptr > (that.value); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.copy< ast::expr_integer::ptr > (that.value); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.copy< ast::expr_istring::ptr > (that.value); + break; + + case symbol_kind::S_expr_level: // expr_level + value.copy< ast::expr_level::ptr > (that.value); + break; + + case symbol_kind::S_expr_method: // expr_method + value.copy< ast::expr_method::ptr > (that.value); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.copy< ast::expr_negate::ptr > (that.value); + break; + + case symbol_kind::S_expr_not: // expr_not + value.copy< ast::expr_not::ptr > (that.value); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.copy< ast::expr_parameters::ptr > (that.value); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.copy< ast::expr_paren::ptr > (that.value); + break; + + case symbol_kind::S_expr_path: // expr_path + value.copy< ast::expr_path::ptr > (that.value); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.copy< ast::expr_reference::ptr > (that.value); + break; + + case symbol_kind::S_expr_self: // expr_self + value.copy< ast::expr_self::ptr > (that.value); + break; + + case symbol_kind::S_expr_size: // expr_size + value.copy< ast::expr_size::ptr > (that.value); + break; + + case symbol_kind::S_expr_string: // expr_string + value.copy< ast::expr_string::ptr > (that.value); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.copy< ast::expr_thisthread::ptr > (that.value); + break; + + case symbol_kind::S_expr_true: // expr_true + value.copy< ast::expr_true::ptr > (that.value); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.copy< ast::expr_tuple::ptr > (that.value); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.copy< ast::expr_undefined::ptr > (that.value); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.copy< ast::expr_vector::ptr > (that.value); + break; + + case symbol_kind::S_include: // include + value.copy< ast::include::ptr > (that.value); + break; + + case symbol_kind::S_program: // program + value.copy< ast::program::ptr > (that.value); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.copy< ast::stmt > (that.value); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.copy< ast::stmt_assign::ptr > (that.value); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.copy< ast::stmt_break::ptr > (that.value); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.copy< ast::stmt_breakpoint::ptr > (that.value); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.copy< ast::stmt_call::ptr > (that.value); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.copy< ast::stmt_case::ptr > (that.value); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.copy< ast::stmt_continue::ptr > (that.value); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.copy< ast::stmt_default::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.copy< ast::stmt_dev::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.copy< ast::stmt_dowhile::ptr > (that.value); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.copy< ast::stmt_endon::ptr > (that.value); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.copy< ast::stmt_expr::ptr > (that.value); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.copy< ast::stmt_for::ptr > (that.value); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.copy< ast::stmt_foreach::ptr > (that.value); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.copy< ast::stmt_if::ptr > (that.value); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.copy< ast::stmt_ifelse::ptr > (that.value); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.copy< ast::stmt_list::ptr > (that.value); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.copy< ast::stmt_notify::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.copy< ast::stmt_prof_begin::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.copy< ast::stmt_prof_end::ptr > (that.value); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.copy< ast::stmt_return::ptr > (that.value); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.copy< ast::stmt_switch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.copy< ast::stmt_wait::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.copy< ast::stmt_waittill::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.copy< ast::stmt_waittillframeend::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.copy< ast::stmt_waittillmatch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.copy< ast::stmt_while::ptr > (that.value); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.copy< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (that.value); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (that.value); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (that.value); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (that.value); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (that.value); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (that.value); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (that.value); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (that.value); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (that.value); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (that.value); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (that.value); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (that.value); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (that.value); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (that.value); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (that.value); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (that.value); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (that.value); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (that.value); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (that.value); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (that.value); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (that.value); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (that.value); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (that.value); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (that.value); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (that.value); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (that.value); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (that.value); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (that.value); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (that.value); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (that.value); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (that.value); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (that.value); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (that.value); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (that.value); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (that.value); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (that.value); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (that.value); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (that.value); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (that.value); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (that.value); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (that.value); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (that.value); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (that.value); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (that.value); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (that.value); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (that.value); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (that.value); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (that.value); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (that.value); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (that.value); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (that.value); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (that.value); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (that.value); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (that.value); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (that.value); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (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 IW6CDEBUG + 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) YY_NOEXCEPT + { + yystack_.pop (n); + } + +#if IW6CDEBUG + 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 // IW6CDEBUG + + 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) YY_NOEXCEPT + { + return yyvalue == yypact_ninf_; + } + + bool + parser::yy_table_value_is_error_ (int yyvalue) YY_NOEXCEPT + { + 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 (lexer)); + 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + yylhs.value.emplace< ast::call > (); + break; + + case symbol_kind::S_declaration: // declaration + yylhs.value.emplace< ast::decl > (); + break; + + case symbol_kind::S_decl_constant: // decl_constant + yylhs.value.emplace< ast::decl_constant::ptr > (); + break; + + case symbol_kind::S_decl_thread: // decl_thread + yylhs.value.emplace< ast::decl_thread::ptr > (); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + yylhs.value.emplace< ast::decl_usingtree::ptr > (); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + yylhs.value.emplace< ast::expr > (); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + yylhs.value.emplace< ast::expr_add_array::ptr > (); + break; + + case symbol_kind::S_expr_anim: // expr_anim + yylhs.value.emplace< ast::expr_anim::ptr > (); + break; + + case symbol_kind::S_expr_animation: // expr_animation + yylhs.value.emplace< ast::expr_animation::ptr > (); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + yylhs.value.emplace< ast::expr_animtree::ptr > (); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + yylhs.value.emplace< ast::expr_arguments::ptr > (); + break; + + case symbol_kind::S_expr_array: // expr_array + yylhs.value.emplace< ast::expr_array::ptr > (); + break; + + case symbol_kind::S_expr_call: // expr_call + yylhs.value.emplace< ast::expr_call::ptr > (); + break; + + case symbol_kind::S_expr_complement: // expr_complement + yylhs.value.emplace< ast::expr_complement::ptr > (); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + yylhs.value.emplace< ast::expr_empty_array::ptr > (); + break; + + case symbol_kind::S_expr_false: // expr_false + yylhs.value.emplace< ast::expr_false::ptr > (); + break; + + case symbol_kind::S_expr_field: // expr_field + yylhs.value.emplace< ast::expr_field::ptr > (); + break; + + case symbol_kind::S_expr_float: // expr_float + yylhs.value.emplace< ast::expr_float::ptr > (); + break; + + case symbol_kind::S_expr_game: // expr_game + yylhs.value.emplace< ast::expr_game::ptr > (); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + yylhs.value.emplace< ast::expr_identifier::ptr > (); + break; + + case symbol_kind::S_expr_integer: // expr_integer + yylhs.value.emplace< ast::expr_integer::ptr > (); + break; + + case symbol_kind::S_expr_istring: // expr_istring + yylhs.value.emplace< ast::expr_istring::ptr > (); + break; + + case symbol_kind::S_expr_level: // expr_level + yylhs.value.emplace< ast::expr_level::ptr > (); + break; + + case symbol_kind::S_expr_method: // expr_method + yylhs.value.emplace< ast::expr_method::ptr > (); + break; + + case symbol_kind::S_expr_negate: // expr_negate + yylhs.value.emplace< ast::expr_negate::ptr > (); + break; + + case symbol_kind::S_expr_not: // expr_not + yylhs.value.emplace< ast::expr_not::ptr > (); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + yylhs.value.emplace< ast::expr_parameters::ptr > (); + break; + + case symbol_kind::S_expr_paren: // expr_paren + yylhs.value.emplace< ast::expr_paren::ptr > (); + break; + + case symbol_kind::S_expr_path: // expr_path + yylhs.value.emplace< ast::expr_path::ptr > (); + break; + + case symbol_kind::S_expr_reference: // expr_reference + yylhs.value.emplace< ast::expr_reference::ptr > (); + break; + + case symbol_kind::S_expr_self: // expr_self + yylhs.value.emplace< ast::expr_self::ptr > (); + break; + + case symbol_kind::S_expr_size: // expr_size + yylhs.value.emplace< ast::expr_size::ptr > (); + break; + + case symbol_kind::S_expr_string: // expr_string + yylhs.value.emplace< ast::expr_string::ptr > (); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + yylhs.value.emplace< ast::expr_thisthread::ptr > (); + break; + + case symbol_kind::S_expr_true: // expr_true + yylhs.value.emplace< ast::expr_true::ptr > (); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + yylhs.value.emplace< ast::expr_tuple::ptr > (); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + yylhs.value.emplace< ast::expr_undefined::ptr > (); + break; + + case symbol_kind::S_expr_vector: // expr_vector + yylhs.value.emplace< ast::expr_vector::ptr > (); + break; + + case symbol_kind::S_include: // include + yylhs.value.emplace< ast::include::ptr > (); + break; + + case symbol_kind::S_program: // program + yylhs.value.emplace< ast::program::ptr > (); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + yylhs.value.emplace< ast::stmt > (); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + yylhs.value.emplace< ast::stmt_assign::ptr > (); + break; + + case symbol_kind::S_stmt_break: // stmt_break + yylhs.value.emplace< ast::stmt_break::ptr > (); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + yylhs.value.emplace< ast::stmt_breakpoint::ptr > (); + break; + + case symbol_kind::S_stmt_call: // stmt_call + yylhs.value.emplace< ast::stmt_call::ptr > (); + break; + + case symbol_kind::S_stmt_case: // stmt_case + yylhs.value.emplace< ast::stmt_case::ptr > (); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + yylhs.value.emplace< ast::stmt_continue::ptr > (); + break; + + case symbol_kind::S_stmt_default: // stmt_default + yylhs.value.emplace< ast::stmt_default::ptr > (); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + yylhs.value.emplace< ast::stmt_dev::ptr > (); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + yylhs.value.emplace< ast::stmt_dowhile::ptr > (); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + yylhs.value.emplace< ast::stmt_endon::ptr > (); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + yylhs.value.emplace< ast::stmt_expr::ptr > (); + break; + + case symbol_kind::S_stmt_for: // stmt_for + yylhs.value.emplace< ast::stmt_for::ptr > (); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + yylhs.value.emplace< ast::stmt_foreach::ptr > (); + break; + + case symbol_kind::S_stmt_if: // stmt_if + yylhs.value.emplace< ast::stmt_if::ptr > (); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + yylhs.value.emplace< ast::stmt_ifelse::ptr > (); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + yylhs.value.emplace< ast::stmt_list::ptr > (); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + yylhs.value.emplace< ast::stmt_notify::ptr > (); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + yylhs.value.emplace< ast::stmt_prof_begin::ptr > (); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + yylhs.value.emplace< ast::stmt_prof_end::ptr > (); + break; + + case symbol_kind::S_stmt_return: // stmt_return + yylhs.value.emplace< ast::stmt_return::ptr > (); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + yylhs.value.emplace< ast::stmt_switch::ptr > (); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + yylhs.value.emplace< ast::stmt_wait::ptr > (); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + yylhs.value.emplace< ast::stmt_waittill::ptr > (); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + yylhs.value.emplace< ast::stmt_waittillframeend::ptr > (); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + yylhs.value.emplace< ast::stmt_waittillmatch::ptr > (); + break; + + case symbol_kind::S_stmt_while: // stmt_while + yylhs.value.emplace< ast::stmt_while::ptr > (); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + yylhs.value.emplace< std::string > (); + 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 261 "parser.ypp" + { ast = std::move(yystack_[0].value.as < ast::program::ptr > ()); } +#line 2020 "parser.cpp" + break; + + case 3: // root: %empty +#line 262 "parser.ypp" + { ast = std::make_unique(yylhs.location); } +#line 2026 "parser.cpp" + break; + + case 4: // program: program inline +#line 267 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::move(yystack_[1].value.as < ast::program::ptr > ()); } +#line 2032 "parser.cpp" + break; + + case 5: // program: program include +#line 269 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::move(yystack_[1].value.as < ast::program::ptr > ()); yylhs.value.as < ast::program::ptr > ()->includes.push_back(std::move(yystack_[0].value.as < ast::include::ptr > ())); } +#line 2038 "parser.cpp" + break; + + case 6: // program: program declaration +#line 271 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::move(yystack_[1].value.as < ast::program::ptr > ()); yylhs.value.as < ast::program::ptr > ()->declarations.push_back(std::move(yystack_[0].value.as < ast::decl > ())); } +#line 2044 "parser.cpp" + break; + + case 7: // program: inline +#line 273 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::make_unique(yylhs.location); } +#line 2050 "parser.cpp" + break; + + case 8: // program: include +#line 275 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::program::ptr > ()->includes.push_back(std::move(yystack_[0].value.as < ast::include::ptr > ())); } +#line 2056 "parser.cpp" + break; + + case 9: // program: declaration +#line 277 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::program::ptr > ()->declarations.push_back(std::move(yystack_[0].value.as < ast::decl > ())); } +#line 2062 "parser.cpp" + break; + + case 10: // inline: "#inline" expr_path ";" +#line 281 "parser.ypp" + { lexer.push_header(yystack_[1].value.as < ast::expr_path::ptr > ()->value); } +#line 2068 "parser.cpp" + break; + + case 11: // include: "#include" expr_path ";" +#line 286 "parser.ypp" + { yylhs.value.as < ast::include::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr_path::ptr > ())); } +#line 2074 "parser.cpp" + break; + + case 12: // declaration: "/#" +#line 290 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_dev_begin = std::make_unique(yylhs.location); } +#line 2080 "parser.cpp" + break; + + case 13: // declaration: "#/" +#line 291 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_dev_end = std::make_unique(yylhs.location); } +#line 2086 "parser.cpp" + break; + + case 14: // declaration: decl_usingtree +#line 292 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_usingtree = std::move(yystack_[0].value.as < ast::decl_usingtree::ptr > ()); } +#line 2092 "parser.cpp" + break; + + case 15: // declaration: decl_constant +#line 293 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_constant = std::move(yystack_[0].value.as < ast::decl_constant::ptr > ()); } +#line 2098 "parser.cpp" + break; + + case 16: // declaration: decl_thread +#line 294 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_thread = std::move(yystack_[0].value.as < ast::decl_thread::ptr > ()); } +#line 2104 "parser.cpp" + break; + + case 17: // decl_usingtree: "#using_animtree" "(" expr_string ")" ";" +#line 299 "parser.ypp" + { lexer.ban_header(yylhs.location); yylhs.value.as < ast::decl_usingtree::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_string::ptr > ())); } +#line 2110 "parser.cpp" + break; + + case 18: // decl_constant: expr_identifier "=" expr ";" +#line 304 "parser.ypp" + { yylhs.value.as < ast::decl_constant::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2116 "parser.cpp" + break; + + case 19: // decl_thread: expr_identifier "(" expr_parameters ")" stmt_block +#line 309 "parser.ypp" + { lexer.ban_header(yylhs.location); yylhs.value.as < ast::decl_thread::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[2].value.as < ast::expr_parameters::ptr > ()), std::move(yystack_[0].value.as < ast::stmt_list::ptr > ())); } +#line 2122 "parser.cpp" + break; + + case 20: // stmt: stmt_block +#line 313 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_list = std::move(yystack_[0].value.as < ast::stmt_list::ptr > ()); } +#line 2128 "parser.cpp" + break; + + case 21: // stmt: stmt_call +#line 314 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_call = std::move(yystack_[0].value.as < ast::stmt_call::ptr > ()); } +#line 2134 "parser.cpp" + break; + + case 22: // stmt: stmt_assign +#line 315 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_assign = std::move(yystack_[0].value.as < ast::stmt_assign::ptr > ()); } +#line 2140 "parser.cpp" + break; + + case 23: // stmt: stmt_endon +#line 316 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_endon = std::move(yystack_[0].value.as < ast::stmt_endon::ptr > ()); } +#line 2146 "parser.cpp" + break; + + case 24: // stmt: stmt_notify +#line 317 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_notify = std::move(yystack_[0].value.as < ast::stmt_notify::ptr > ()); } +#line 2152 "parser.cpp" + break; + + case 25: // stmt: stmt_wait +#line 318 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_wait = std::move(yystack_[0].value.as < ast::stmt_wait::ptr > ()); } +#line 2158 "parser.cpp" + break; + + case 26: // stmt: stmt_waittill +#line 319 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_waittill = std::move(yystack_[0].value.as < ast::stmt_waittill::ptr > ()); } +#line 2164 "parser.cpp" + break; + + case 27: // stmt: stmt_waittillmatch +#line 320 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_waittillmatch = std::move(yystack_[0].value.as < ast::stmt_waittillmatch::ptr > ()); } +#line 2170 "parser.cpp" + break; + + case 28: // stmt: stmt_waittillframeend +#line 321 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_waittillframeend = std::move(yystack_[0].value.as < ast::stmt_waittillframeend::ptr > ()); } +#line 2176 "parser.cpp" + break; + + case 29: // stmt: stmt_if +#line 322 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_if = std::move(yystack_[0].value.as < ast::stmt_if::ptr > ()); } +#line 2182 "parser.cpp" + break; + + case 30: // stmt: stmt_ifelse +#line 323 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_ifelse = std::move(yystack_[0].value.as < ast::stmt_ifelse::ptr > ()); } +#line 2188 "parser.cpp" + break; + + case 31: // stmt: stmt_while +#line 324 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_while = std::move(yystack_[0].value.as < ast::stmt_while::ptr > ()); } +#line 2194 "parser.cpp" + break; + + case 32: // stmt: stmt_dowhile +#line 325 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_dowhile = std::move(yystack_[0].value.as < ast::stmt_dowhile::ptr > ()); } +#line 2200 "parser.cpp" + break; + + case 33: // stmt: stmt_for +#line 326 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_for = std::move(yystack_[0].value.as < ast::stmt_for::ptr > ()); } +#line 2206 "parser.cpp" + break; + + case 34: // stmt: stmt_foreach +#line 327 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_foreach = std::move(yystack_[0].value.as < ast::stmt_foreach::ptr > ()); } +#line 2212 "parser.cpp" + break; + + case 35: // stmt: stmt_switch +#line 328 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_switch = std::move(yystack_[0].value.as < ast::stmt_switch::ptr > ()); } +#line 2218 "parser.cpp" + break; + + case 36: // stmt: stmt_case +#line 329 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_case = std::move(yystack_[0].value.as < ast::stmt_case::ptr > ()); } +#line 2224 "parser.cpp" + break; + + case 37: // stmt: stmt_default +#line 330 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_default = std::move(yystack_[0].value.as < ast::stmt_default::ptr > ()); } +#line 2230 "parser.cpp" + break; + + case 38: // stmt: stmt_break +#line 331 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_break = std::move(yystack_[0].value.as < ast::stmt_break::ptr > ()); } +#line 2236 "parser.cpp" + break; + + case 39: // stmt: stmt_continue +#line 332 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_continue = std::move(yystack_[0].value.as < ast::stmt_continue::ptr > ()); } +#line 2242 "parser.cpp" + break; + + case 40: // stmt: stmt_return +#line 333 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_return = std::move(yystack_[0].value.as < ast::stmt_return::ptr > ()); } +#line 2248 "parser.cpp" + break; + + case 41: // stmt: stmt_breakpoint +#line 334 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_breakpoint = std::move(yystack_[0].value.as < ast::stmt_breakpoint::ptr > ()); } +#line 2254 "parser.cpp" + break; + + case 42: // stmt: stmt_prof_begin +#line 335 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_prof_begin = std::move(yystack_[0].value.as < ast::stmt_prof_begin::ptr > ()); } +#line 2260 "parser.cpp" + break; + + case 43: // stmt: stmt_prof_end +#line 336 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_prof_end = std::move(yystack_[0].value.as < ast::stmt_prof_end::ptr > ()); } +#line 2266 "parser.cpp" + break; + + case 44: // stmt_or_dev: stmt +#line 340 "parser.ypp" + { yylhs.value.as < ast::stmt > () = std::move(yystack_[0].value.as < ast::stmt > ()); } +#line 2272 "parser.cpp" + break; + + case 45: // stmt_or_dev: stmt_dev +#line 341 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_dev = std::move(yystack_[0].value.as < ast::stmt_dev::ptr > ()); } +#line 2278 "parser.cpp" + break; + + case 46: // stmt_list: stmt_list stmt +#line 346 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::move(yystack_[1].value.as < ast::stmt_list::ptr > ()); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2284 "parser.cpp" + break; + + case 47: // stmt_list: stmt +#line 348 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2290 "parser.cpp" + break; + + case 48: // stmt_or_dev_list: stmt_or_dev_list stmt_or_dev +#line 353 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::move(yystack_[1].value.as < ast::stmt_list::ptr > ()); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2296 "parser.cpp" + break; + + case 49: // stmt_or_dev_list: stmt_or_dev +#line 355 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2302 "parser.cpp" + break; + + case 50: // stmt_dev: "/#" stmt_list "#/" +#line 359 "parser.ypp" + { yylhs.value.as < ast::stmt_dev::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::stmt_list::ptr > ())); } +#line 2308 "parser.cpp" + break; + + case 51: // stmt_dev: "/#" "#/" +#line 360 "parser.ypp" + { yylhs.value.as < ast::stmt_dev::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2314 "parser.cpp" + break; + + case 52: // stmt_block: "{" stmt_or_dev_list "}" +#line 364 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::move(yystack_[1].value.as < ast::stmt_list::ptr > ()); } +#line 2320 "parser.cpp" + break; + + case 53: // stmt_block: "{" "}" +#line 365 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::make_unique(yylhs.location); } +#line 2326 "parser.cpp" + break; + + case 54: // stmt_expr: expr_assign +#line 370 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2332 "parser.cpp" + break; + + case 55: // stmt_expr: expr_increment +#line 372 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2338 "parser.cpp" + break; + + case 56: // stmt_expr: expr_decrement +#line 374 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2344 "parser.cpp" + break; + + case 57: // stmt_expr: %empty +#line 376 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2350 "parser.cpp" + break; + + case 58: // stmt_call: expr_call ";" +#line 381 "parser.ypp" + { yylhs.value.as < ast::stmt_call::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_call::ptr > ()))); } +#line 2356 "parser.cpp" + break; + + case 59: // stmt_call: expr_method ";" +#line 383 "parser.ypp" + { yylhs.value.as < ast::stmt_call::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_method::ptr > ()))); } +#line 2362 "parser.cpp" + break; + + case 60: // stmt_assign: expr_assign ";" +#line 388 "parser.ypp" + { yylhs.value.as < ast::stmt_assign::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2368 "parser.cpp" + break; + + case 61: // stmt_assign: expr_increment ";" +#line 390 "parser.ypp" + { yylhs.value.as < ast::stmt_assign::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2374 "parser.cpp" + break; + + case 62: // stmt_assign: expr_decrement ";" +#line 392 "parser.ypp" + { yylhs.value.as < ast::stmt_assign::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2380 "parser.cpp" + break; + + case 63: // stmt_endon: expr_object "endon" "(" expr ")" ";" +#line 397 "parser.ypp" + { yylhs.value.as < ast::stmt_endon::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ())); } +#line 2386 "parser.cpp" + break; + + case 64: // stmt_notify: expr_object "notify" "(" expr "," expr_arguments_no_empty ")" ";" +#line 402 "parser.ypp" + { yylhs.value.as < ast::stmt_notify::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < ast::expr > ()), std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2392 "parser.cpp" + break; + + case 65: // stmt_notify: expr_object "notify" "(" expr ")" ";" +#line 404 "parser.ypp" + { yylhs.value.as < ast::stmt_notify::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::make_unique(yylhs.location)); } +#line 2398 "parser.cpp" + break; + + case 66: // stmt_wait: "wait" expr ";" +#line 409 "parser.ypp" + { yylhs.value.as < ast::stmt_wait::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2404 "parser.cpp" + break; + + case 67: // stmt_waittill: expr_object "waittill" "(" expr "," expr_arguments_no_empty ")" ";" +#line 414 "parser.ypp" + { yylhs.value.as < ast::stmt_waittill::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < ast::expr > ()), std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2410 "parser.cpp" + break; + + case 68: // stmt_waittill: expr_object "waittill" "(" expr ")" ";" +#line 416 "parser.ypp" + { yylhs.value.as < ast::stmt_waittill::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::make_unique(yylhs.location)); } +#line 2416 "parser.cpp" + break; + + case 69: // stmt_waittillmatch: expr_object "waittillmatch" "(" expr "," expr_arguments_no_empty ")" ";" +#line 421 "parser.ypp" + { yylhs.value.as < ast::stmt_waittillmatch::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < ast::expr > ()), std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2422 "parser.cpp" + break; + + case 70: // stmt_waittillmatch: expr_object "waittillmatch" "(" expr ")" ";" +#line 423 "parser.ypp" + { yylhs.value.as < ast::stmt_waittillmatch::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::make_unique(yylhs.location)); } +#line 2428 "parser.cpp" + break; + + case 71: // stmt_waittillframeend: "waittillframeend" ";" +#line 428 "parser.ypp" + { yylhs.value.as < ast::stmt_waittillframeend::ptr > () = std::make_unique(yylhs.location); } +#line 2434 "parser.cpp" + break; + + case 72: // stmt_if: "if" "(" expr ")" stmt +#line 433 "parser.ypp" + { yylhs.value.as < ast::stmt_if::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2440 "parser.cpp" + break; + + case 73: // stmt_ifelse: "if" "(" expr ")" stmt "else" stmt +#line 438 "parser.ypp" + { yylhs.value.as < ast::stmt_ifelse::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::stmt > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2446 "parser.cpp" + break; + + case 74: // stmt_while: "while" "(" expr ")" stmt +#line 443 "parser.ypp" + { yylhs.value.as < ast::stmt_while::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2452 "parser.cpp" + break; + + case 75: // stmt_dowhile: "do" stmt "while" "(" expr ")" ";" +#line 448 "parser.ypp" + { yylhs.value.as < ast::stmt_dowhile::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[5].value.as < ast::stmt > ())); } +#line 2458 "parser.cpp" + break; + + case 76: // stmt_for: "for" "(" stmt_expr ";" expr_or_empty ";" stmt_expr ")" stmt +#line 453 "parser.ypp" + { yylhs.value.as < ast::stmt_for::ptr > () = std::make_unique(yylhs.location, ast::stmt(std::move(yystack_[6].value.as < ast::stmt_expr::ptr > ())), std::move(yystack_[4].value.as < ast::expr > ()), ast::stmt(std::move(yystack_[2].value.as < ast::stmt_expr::ptr > ())), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2464 "parser.cpp" + break; + + case 77: // stmt_foreach: "foreach" "(" expr_identifier "in" expr ")" stmt +#line 458 "parser.ypp" + { yylhs.value.as < ast::stmt_foreach::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[4].value.as < ast::expr_identifier::ptr > ())), std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2470 "parser.cpp" + break; + + case 78: // stmt_foreach: "foreach" "(" expr_identifier "," expr_identifier "in" expr ")" stmt +#line 460 "parser.ypp" + { yylhs.value.as < ast::stmt_foreach::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[6].value.as < ast::expr_identifier::ptr > ())), ast::expr(std::move(yystack_[4].value.as < ast::expr_identifier::ptr > ())), std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2476 "parser.cpp" + break; + + case 79: // stmt_switch: "switch" "(" expr ")" stmt_block +#line 465 "parser.ypp" + { yylhs.value.as < ast::stmt_switch::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt_list::ptr > ())); } +#line 2482 "parser.cpp" + break; + + case 80: // stmt_case: "case" expr_integer ":" +#line 470 "parser.ypp" + { yylhs.value.as < ast::stmt_case::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_integer::ptr > ())), std::make_unique(yylhs.location)); } +#line 2488 "parser.cpp" + break; + + case 81: // stmt_case: "case" expr_string ":" +#line 472 "parser.ypp" + { yylhs.value.as < ast::stmt_case::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_string::ptr > ())), std::make_unique(yylhs.location)); } +#line 2494 "parser.cpp" + break; + + case 82: // stmt_default: "default" ":" +#line 477 "parser.ypp" + { yylhs.value.as < ast::stmt_default::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2500 "parser.cpp" + break; + + case 83: // stmt_break: "break" ";" +#line 482 "parser.ypp" + { yylhs.value.as < ast::stmt_break::ptr > () = std::make_unique(yylhs.location); } +#line 2506 "parser.cpp" + break; + + case 84: // stmt_continue: "continue" ";" +#line 487 "parser.ypp" + { yylhs.value.as < ast::stmt_continue::ptr > () = std::make_unique(yylhs.location); } +#line 2512 "parser.cpp" + break; + + case 85: // stmt_return: "return" expr ";" +#line 492 "parser.ypp" + { yylhs.value.as < ast::stmt_return::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2518 "parser.cpp" + break; + + case 86: // stmt_return: "return" ";" +#line 494 "parser.ypp" + { yylhs.value.as < ast::stmt_return::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2524 "parser.cpp" + break; + + case 87: // stmt_breakpoint: "breakpoint" ";" +#line 499 "parser.ypp" + { yylhs.value.as < ast::stmt_breakpoint::ptr > () = std::make_unique(yylhs.location); } +#line 2530 "parser.cpp" + break; + + case 88: // stmt_prof_begin: "prof_begin" "(" expr_arguments ")" ";" +#line 504 "parser.ypp" + { yylhs.value.as < ast::stmt_prof_begin::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2536 "parser.cpp" + break; + + case 89: // stmt_prof_end: "prof_end" "(" expr_arguments ")" ";" +#line 509 "parser.ypp" + { yylhs.value.as < ast::stmt_prof_end::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2542 "parser.cpp" + break; + + case 90: // expr: expr_ternary +#line 513 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2548 "parser.cpp" + break; + + case 91: // expr: expr_binary +#line 514 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2554 "parser.cpp" + break; + + case 92: // expr: expr_primitive +#line 515 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2560 "parser.cpp" + break; + + case 93: // expr_or_empty: expr +#line 519 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2566 "parser.cpp" + break; + + case 94: // expr_or_empty: %empty +#line 520 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location); } +#line 2572 "parser.cpp" + break; + + case 95: // expr_assign: expr_tuple "=" expr +#line 525 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2578 "parser.cpp" + break; + + case 96: // expr_assign: expr_object "=" expr +#line 527 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2584 "parser.cpp" + break; + + case 97: // expr_assign: expr_object "|=" expr +#line 529 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2590 "parser.cpp" + break; + + case 98: // expr_assign: expr_object "&=" expr +#line 531 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2596 "parser.cpp" + break; + + case 99: // expr_assign: expr_object "^=" expr +#line 533 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2602 "parser.cpp" + break; + + case 100: // expr_assign: expr_object "<<=" expr +#line 535 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()),std::move( yystack_[0].value.as < ast::expr > ())); } +#line 2608 "parser.cpp" + break; + + case 101: // expr_assign: expr_object ">>=" expr +#line 537 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2614 "parser.cpp" + break; + + case 102: // expr_assign: expr_object "+=" expr +#line 539 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2620 "parser.cpp" + break; + + case 103: // expr_assign: expr_object "-=" expr +#line 541 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2626 "parser.cpp" + break; + + case 104: // expr_assign: expr_object "*=" expr +#line 543 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2632 "parser.cpp" + break; + + case 105: // expr_assign: expr_object "/=" expr +#line 545 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2638 "parser.cpp" + break; + + case 106: // expr_assign: expr_object "%=" expr +#line 547 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2644 "parser.cpp" + break; + + case 107: // expr_increment: "++" expr_object +#line 552 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ()), true); } +#line 2650 "parser.cpp" + break; + + case 108: // expr_increment: expr_object "++" +#line 554 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), false); } +#line 2656 "parser.cpp" + break; + + case 109: // expr_decrement: "--" expr_object +#line 559 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ()), true); } +#line 2662 "parser.cpp" + break; + + case 110: // expr_decrement: expr_object "--" +#line 561 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), false); } +#line 2668 "parser.cpp" + break; + + case 111: // expr_ternary: expr "?" expr ":" expr +#line 566 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2674 "parser.cpp" + break; + + case 112: // expr_binary: expr "||" expr +#line 571 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2680 "parser.cpp" + break; + + case 113: // expr_binary: expr "&&" expr +#line 573 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2686 "parser.cpp" + break; + + case 114: // expr_binary: expr "==" expr +#line 575 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2692 "parser.cpp" + break; + + case 115: // expr_binary: expr "!=" expr +#line 577 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2698 "parser.cpp" + break; + + case 116: // expr_binary: expr "<=" expr +#line 579 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2704 "parser.cpp" + break; + + case 117: // expr_binary: expr ">=" expr +#line 581 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2710 "parser.cpp" + break; + + case 118: // expr_binary: expr "<" expr +#line 583 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2716 "parser.cpp" + break; + + case 119: // expr_binary: expr ">" expr +#line 585 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2722 "parser.cpp" + break; + + case 120: // expr_binary: expr "|" expr +#line 587 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2728 "parser.cpp" + break; + + case 121: // expr_binary: expr "&" expr +#line 589 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2734 "parser.cpp" + break; + + case 122: // expr_binary: expr "^" expr +#line 591 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2740 "parser.cpp" + break; + + case 123: // expr_binary: expr "<<" expr +#line 593 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2746 "parser.cpp" + break; + + case 124: // expr_binary: expr ">>" expr +#line 595 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2752 "parser.cpp" + break; + + case 125: // expr_binary: expr "+" expr +#line 597 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2758 "parser.cpp" + break; + + case 126: // expr_binary: expr "-" expr +#line 599 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2764 "parser.cpp" + break; + + case 127: // expr_binary: expr "*" expr +#line 601 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2770 "parser.cpp" + break; + + case 128: // expr_binary: expr "/" expr +#line 603 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2776 "parser.cpp" + break; + + case 129: // expr_binary: expr "%" expr +#line 605 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2782 "parser.cpp" + break; + + case 130: // expr_primitive: expr_complement +#line 609 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_complement::ptr > ()); } +#line 2788 "parser.cpp" + break; + + case 131: // expr_primitive: expr_negate +#line 610 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_negate::ptr > ()); } +#line 2794 "parser.cpp" + break; + + case 132: // expr_primitive: expr_not +#line 611 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_not::ptr > ()); } +#line 2800 "parser.cpp" + break; + + case 133: // expr_primitive: expr_call +#line 612 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_call::ptr > ()); } +#line 2806 "parser.cpp" + break; + + case 134: // expr_primitive: expr_method +#line 613 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_method::ptr > ()); } +#line 2812 "parser.cpp" + break; + + case 135: // expr_primitive: expr_add_array +#line 614 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_add_array::ptr > ()); } +#line 2818 "parser.cpp" + break; + + case 136: // expr_primitive: expr_reference +#line 615 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_reference::ptr > ()); } +#line 2824 "parser.cpp" + break; + + case 137: // expr_primitive: expr_array +#line 616 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_array::ptr > ()); } +#line 2830 "parser.cpp" + break; + + case 138: // expr_primitive: expr_field +#line 617 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_field::ptr > ()); } +#line 2836 "parser.cpp" + break; + + case 139: // expr_primitive: expr_size +#line 618 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_size::ptr > ()); } +#line 2842 "parser.cpp" + break; + + case 140: // expr_primitive: expr_paren +#line 619 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_paren::ptr > ()); } +#line 2848 "parser.cpp" + break; + + case 141: // expr_primitive: expr_thisthread +#line 620 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_thisthread::ptr > ()); } +#line 2854 "parser.cpp" + break; + + case 142: // expr_primitive: expr_empty_array +#line 621 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_empty_array::ptr > ()); } +#line 2860 "parser.cpp" + break; + + case 143: // expr_primitive: expr_undefined +#line 622 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_undefined::ptr > ()); } +#line 2866 "parser.cpp" + break; + + case 144: // expr_primitive: expr_game +#line 623 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_game::ptr > ()); } +#line 2872 "parser.cpp" + break; + + case 145: // expr_primitive: expr_self +#line 624 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_self::ptr > ()); } +#line 2878 "parser.cpp" + break; + + case 146: // expr_primitive: expr_anim +#line 625 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_anim::ptr > ()); } +#line 2884 "parser.cpp" + break; + + case 147: // expr_primitive: expr_level +#line 626 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_level::ptr > ()); } +#line 2890 "parser.cpp" + break; + + case 148: // expr_primitive: expr_animation +#line 627 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_animation::ptr > ()); } +#line 2896 "parser.cpp" + break; + + case 149: // expr_primitive: expr_animtree +#line 628 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_animtree::ptr > ()); } +#line 2902 "parser.cpp" + break; + + case 150: // expr_primitive: expr_identifier +#line 629 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()); } +#line 2908 "parser.cpp" + break; + + case 151: // expr_primitive: expr_istring +#line 630 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_istring::ptr > ()); } +#line 2914 "parser.cpp" + break; + + case 152: // expr_primitive: expr_string +#line 631 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_string::ptr > ()); } +#line 2920 "parser.cpp" + break; + + case 153: // expr_primitive: expr_vector +#line 632 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_vector::ptr > ()); } +#line 2926 "parser.cpp" + break; + + case 154: // expr_primitive: expr_float +#line 633 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_float::ptr > ()); } +#line 2932 "parser.cpp" + break; + + case 155: // expr_primitive: expr_integer +#line 634 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_integer::ptr > ()); } +#line 2938 "parser.cpp" + break; + + case 156: // expr_primitive: expr_false +#line 635 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_false::ptr > ()); } +#line 2944 "parser.cpp" + break; + + case 157: // expr_primitive: expr_true +#line 636 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_true::ptr > ()); } +#line 2950 "parser.cpp" + break; + + case 158: // expr_complement: "~" expr +#line 641 "parser.ypp" + { yylhs.value.as < ast::expr_complement::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2956 "parser.cpp" + break; + + case 159: // expr_negate: "-" expr_identifier +#line 646 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()))); } +#line 2962 "parser.cpp" + break; + + case 160: // expr_negate: "-" expr_paren +#line 648 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_paren::ptr > ()))); } +#line 2968 "parser.cpp" + break; + + case 161: // expr_negate: "-" expr_array +#line 650 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_array::ptr > ()))); } +#line 2974 "parser.cpp" + break; + + case 162: // expr_negate: "-" expr_field +#line 652 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_field::ptr > ()))); } +#line 2980 "parser.cpp" + break; + + case 163: // expr_not: "!" expr +#line 657 "parser.ypp" + { yylhs.value.as < ast::expr_not::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2986 "parser.cpp" + break; + + case 164: // expr_call: expr_function +#line 661 "parser.ypp" + { yylhs.value.as < ast::expr_call::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::call > ())); } +#line 2992 "parser.cpp" + break; + + case 165: // expr_call: expr_pointer +#line 662 "parser.ypp" + { yylhs.value.as < ast::expr_call::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::call > ())); } +#line 2998 "parser.cpp" + break; + + case 166: // expr_method: expr_object expr_function +#line 665 "parser.ypp" + { yylhs.value.as < ast::expr_method::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::call > ())); } +#line 3004 "parser.cpp" + break; + + case 167: // expr_method: expr_object expr_pointer +#line 666 "parser.ypp" + { yylhs.value.as < ast::expr_method::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::call > ())); } +#line 3010 "parser.cpp" + break; + + case 168: // expr_function: expr_identifier "(" expr_arguments ")" +#line 671 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::normal); } +#line 3016 "parser.cpp" + break; + + case 169: // expr_function: expr_path "::" expr_identifier "(" expr_arguments ")" +#line 673 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr_path::ptr > ()), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::normal); } +#line 3022 "parser.cpp" + break; + + case 170: // expr_function: "thread" expr_identifier "(" expr_arguments ")" +#line 675 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::thread); } +#line 3028 "parser.cpp" + break; + + case 171: // expr_function: "thread" expr_path "::" expr_identifier "(" expr_arguments ")" +#line 677 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr_path::ptr > ()), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::thread); } +#line 3034 "parser.cpp" + break; + + case 172: // expr_function: "childthread" expr_identifier "(" expr_arguments ")" +#line 679 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::childthread); } +#line 3040 "parser.cpp" + break; + + case 173: // expr_function: "childthread" expr_path "::" expr_identifier "(" expr_arguments ")" +#line 681 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr_path::ptr > ()), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::childthread); } +#line 3046 "parser.cpp" + break; + + case 174: // expr_pointer: "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 686 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::normal); } +#line 3052 "parser.cpp" + break; + + case 175: // expr_pointer: "thread" "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 688 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::thread); } +#line 3058 "parser.cpp" + break; + + case 176: // expr_pointer: "childthread" "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 690 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::childthread); } +#line 3064 "parser.cpp" + break; + + case 177: // expr_pointer: "call" "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 692 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::builtin); } +#line 3070 "parser.cpp" + break; + + case 178: // expr_add_array: "[" expr_arguments_no_empty "]" +#line 697 "parser.ypp" + { yylhs.value.as < ast::expr_add_array::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ())); } +#line 3076 "parser.cpp" + break; + + case 179: // expr_parameters: expr_parameters "," expr_identifier +#line 702 "parser.ypp" + { yylhs.value.as < ast::expr_parameters::ptr > () = std::move(yystack_[2].value.as < ast::expr_parameters::ptr > ()); yylhs.value.as < ast::expr_parameters::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3082 "parser.cpp" + break; + + case 180: // expr_parameters: expr_identifier +#line 704 "parser.ypp" + { yylhs.value.as < ast::expr_parameters::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::expr_parameters::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3088 "parser.cpp" + break; + + case 181: // expr_parameters: %empty +#line 706 "parser.ypp" + { yylhs.value.as < ast::expr_parameters::ptr > () = std::make_unique(yylhs.location); } +#line 3094 "parser.cpp" + break; + + case 182: // expr_arguments: expr_arguments_no_empty +#line 711 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::move(yystack_[0].value.as < ast::expr_arguments::ptr > ()); } +#line 3100 "parser.cpp" + break; + + case 183: // expr_arguments: %empty +#line 713 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::make_unique(yylhs.location); } +#line 3106 "parser.cpp" + break; + + case 184: // expr_arguments_no_empty: expr_arguments "," expr +#line 718 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ()); yylhs.value.as < ast::expr_arguments::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3112 "parser.cpp" + break; + + case 185: // expr_arguments_no_empty: expr +#line 720 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::expr_arguments::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3118 "parser.cpp" + break; + + case 186: // expr_reference: "::" expr_identifier +#line 725 "parser.ypp" + { yylhs.value.as < ast::expr_reference::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3124 "parser.cpp" + break; + + case 187: // expr_reference: expr_path "::" expr_identifier +#line 727 "parser.ypp" + { yylhs.value.as < ast::expr_reference::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_path::ptr > ()), std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3130 "parser.cpp" + break; + + case 188: // expr_tuple: "[" expr_tuple_arguments "]" +#line 732 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[1].value.as < ast::expr_tuple::ptr > ()); } +#line 3136 "parser.cpp" + break; + + case 189: // expr_tuple_arguments: expr_tuple_arguments "," expr_tuple_types +#line 737 "parser.ypp" + { yylhs.value.as < ast::expr_tuple::ptr > () = std::move(yystack_[2].value.as < ast::expr_tuple::ptr > ()); yylhs.value.as < ast::expr_tuple::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3142 "parser.cpp" + break; + + case 190: // expr_tuple_arguments: expr_tuple_types +#line 739 "parser.ypp" + { yylhs.value.as < ast::expr_tuple::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::expr_tuple::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3148 "parser.cpp" + break; + + case 191: // expr_tuple_types: expr_array +#line 743 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_array::ptr > ()); } +#line 3154 "parser.cpp" + break; + + case 192: // expr_tuple_types: expr_field +#line 744 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_field::ptr > ()); } +#line 3160 "parser.cpp" + break; + + case 193: // expr_tuple_types: expr_identifier +#line 745 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()); } +#line 3166 "parser.cpp" + break; + + case 194: // expr_array: expr_object "[" expr "]" +#line 750 "parser.ypp" + { yylhs.value.as < ast::expr_array::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[3].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr > ())); } +#line 3172 "parser.cpp" + break; + + case 195: // expr_field: expr_object "." expr_identifier_nosize +#line 755 "parser.ypp" + { yylhs.value.as < ast::expr_field::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3178 "parser.cpp" + break; + + case 196: // expr_size: expr_object "." "size" +#line 760 "parser.ypp" + { yylhs.value.as < ast::expr_size::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ())); } +#line 3184 "parser.cpp" + break; + + case 197: // expr_paren: "(" expr ")" +#line 765 "parser.ypp" + { yylhs.value.as < ast::expr_paren::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 3190 "parser.cpp" + break; + + case 198: // expr_object: expr_call +#line 769 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_call::ptr > ()); } +#line 3196 "parser.cpp" + break; + + case 199: // expr_object: expr_method +#line 770 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_method::ptr > ()); } +#line 3202 "parser.cpp" + break; + + case 200: // expr_object: expr_array +#line 771 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_array::ptr > ()); } +#line 3208 "parser.cpp" + break; + + case 201: // expr_object: expr_field +#line 772 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_field::ptr > ()); } +#line 3214 "parser.cpp" + break; + + case 202: // expr_object: expr_game +#line 773 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_game::ptr > ()); } +#line 3220 "parser.cpp" + break; + + case 203: // expr_object: expr_self +#line 774 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_self::ptr > ()); } +#line 3226 "parser.cpp" + break; + + case 204: // expr_object: expr_anim +#line 775 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_anim::ptr > ()); } +#line 3232 "parser.cpp" + break; + + case 205: // expr_object: expr_level +#line 776 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_level::ptr > ()); } +#line 3238 "parser.cpp" + break; + + case 206: // expr_object: expr_identifier +#line 777 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()); } +#line 3244 "parser.cpp" + break; + + case 207: // expr_thisthread: "thisthread" +#line 782 "parser.ypp" + { yylhs.value.as < ast::expr_thisthread::ptr > () = std::make_unique(yylhs.location); } +#line 3250 "parser.cpp" + break; + + case 208: // expr_empty_array: "[" "]" +#line 787 "parser.ypp" + { yylhs.value.as < ast::expr_empty_array::ptr > () = std::make_unique(yylhs.location); } +#line 3256 "parser.cpp" + break; + + case 209: // expr_undefined: "undefined" +#line 792 "parser.ypp" + { yylhs.value.as < ast::expr_undefined::ptr > () = std::make_unique(yylhs.location); } +#line 3262 "parser.cpp" + break; + + case 210: // expr_game: "game" +#line 797 "parser.ypp" + { yylhs.value.as < ast::expr_game::ptr > () = std::make_unique(yylhs.location); } +#line 3268 "parser.cpp" + break; + + case 211: // expr_self: "self" +#line 802 "parser.ypp" + { yylhs.value.as < ast::expr_self::ptr > () = std::make_unique(yylhs.location); } +#line 3274 "parser.cpp" + break; + + case 212: // expr_anim: "anim" +#line 807 "parser.ypp" + { yylhs.value.as < ast::expr_anim::ptr > () = std::make_unique(yylhs.location); } +#line 3280 "parser.cpp" + break; + + case 213: // expr_level: "level" +#line 812 "parser.ypp" + { yylhs.value.as < ast::expr_level::ptr > () = std::make_unique(yylhs.location); } +#line 3286 "parser.cpp" + break; + + case 214: // expr_animation: "%" "identifier" +#line 817 "parser.ypp" + { yylhs.value.as < ast::expr_animation::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3292 "parser.cpp" + break; + + case 215: // expr_animtree: "#animtree" +#line 822 "parser.ypp" + { yylhs.value.as < ast::expr_animtree::ptr > () = std::make_unique(yylhs.location); } +#line 3298 "parser.cpp" + break; + + case 216: // expr_identifier_nosize: "identifier" +#line 827 "parser.ypp" + { yylhs.value.as < ast::expr_identifier::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3304 "parser.cpp" + break; + + case 217: // expr_identifier: "identifier" +#line 832 "parser.ypp" + { yylhs.value.as < ast::expr_identifier::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3310 "parser.cpp" + break; + + case 218: // expr_identifier: "size" +#line 834 "parser.ypp" + { yylhs.value.as < ast::expr_identifier::ptr > () = std::make_unique(yylhs.location, "size"); } +#line 3316 "parser.cpp" + break; + + case 219: // expr_path: "identifier" +#line 839 "parser.ypp" + { yylhs.value.as < ast::expr_path::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3322 "parser.cpp" + break; + + case 220: // expr_path: "path" +#line 841 "parser.ypp" + { yylhs.value.as < ast::expr_path::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3328 "parser.cpp" + break; + + case 221: // expr_istring: "localized string" +#line 846 "parser.ypp" + { yylhs.value.as < ast::expr_istring::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3334 "parser.cpp" + break; + + case 222: // expr_string: "string literal" +#line 851 "parser.ypp" + { yylhs.value.as < ast::expr_string::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3340 "parser.cpp" + break; + + case 223: // expr_vector: "(" expr "," expr "," expr ")" +#line 856 "parser.ypp" + { yylhs.value.as < ast::expr_vector::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[3].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr > ())); } +#line 3346 "parser.cpp" + break; + + case 224: // expr_float: "-" "float" +#line 861 "parser.ypp" + { yylhs.value.as < ast::expr_float::ptr > () = std::make_unique(yylhs.location, "-" + yystack_[0].value.as < std::string > ()); } +#line 3352 "parser.cpp" + break; + + case 225: // expr_float: "float" +#line 863 "parser.ypp" + { yylhs.value.as < ast::expr_float::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3358 "parser.cpp" + break; + + case 226: // expr_integer: "-" "integer" +#line 868 "parser.ypp" + { yylhs.value.as < ast::expr_integer::ptr > () = std::make_unique(yylhs.location, "-" + yystack_[0].value.as < std::string > ()); } +#line 3364 "parser.cpp" + break; + + case 227: // expr_integer: "integer" +#line 870 "parser.ypp" + { yylhs.value.as < ast::expr_integer::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3370 "parser.cpp" + break; + + case 228: // expr_false: "false" +#line 875 "parser.ypp" + { yylhs.value.as < ast::expr_false::ptr > () = std::make_unique(yylhs.location); } +#line 3376 "parser.cpp" + break; + + case 229: // expr_true: "true" +#line 880 "parser.ypp" + { yylhs.value.as < ast::expr_true::ptr > () = std::make_unique(yylhs.location); } +#line 3382 "parser.cpp" + break; + + +#line 3386 "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", "#define", "#undef", "#ifdef", + "#ifndef", "#if", "#elif", "#else", "#endif", "/#", "#/", "#inline", + "#include", "#using_animtree", "#animtree", "endon", "notify", "wait", + "waittill", "waittillmatch", "waittillframeend", "if", "else", "do", + "while", "for", "foreach", "in", "switch", "case", "default", "break", + "continue", "return", "breakpoint", "prof_begin", "prof_end", "thread", + "childthread", "thisthread", "call", "true", "false", "undefined", + "size", "game", "self", "anim", "level", "(", ")", "{", "}", "[", "]", + ",", ".", "::", ":", ";", "?", "++", "--", "<<", ">>", "||", "&&", "==", + "!=", "<=", ">=", "<", ">", "!", "~", "=", "+=", "-=", "*=", "/=", "%=", + "|=", "&=", "^=", ">>=", "<<=", "|", "&", "^", "+", "-", "*", "/", "%", + "path", "identifier", "string literal", "localized string", "float", + "integer", "SIZEOF", "ADD_ARRAY", "THEN", "TERN", "NEG", "ANIMREF", + "PREINC", "PREDEC", "POSTINC", "POSTDEC", "$accept", "root", "program", + "inline", "include", "declaration", "decl_usingtree", "decl_constant", + "decl_thread", "stmt", "stmt_or_dev", "stmt_list", "stmt_or_dev_list", + "stmt_dev", "stmt_block", "stmt_expr", "stmt_call", "stmt_assign", + "stmt_endon", "stmt_notify", "stmt_wait", "stmt_waittill", + "stmt_waittillmatch", "stmt_waittillframeend", "stmt_if", "stmt_ifelse", + "stmt_while", "stmt_dowhile", "stmt_for", "stmt_foreach", "stmt_switch", + "stmt_case", "stmt_default", "stmt_break", "stmt_continue", + "stmt_return", "stmt_breakpoint", "stmt_prof_begin", "stmt_prof_end", + "expr", "expr_or_empty", "expr_assign", "expr_increment", + "expr_decrement", "expr_ternary", "expr_binary", "expr_primitive", + "expr_complement", "expr_negate", "expr_not", "expr_call", "expr_method", + "expr_function", "expr_pointer", "expr_add_array", "expr_parameters", + "expr_arguments", "expr_arguments_no_empty", "expr_reference", + "expr_tuple", "expr_tuple_arguments", "expr_tuple_types", "expr_array", + "expr_field", "expr_size", "expr_paren", "expr_object", + "expr_thisthread", "expr_empty_array", "expr_undefined", "expr_game", + "expr_self", "expr_anim", "expr_level", "expr_animation", + "expr_animtree", "expr_identifier_nosize", "expr_identifier", + "expr_path", "expr_istring", "expr_string", "expr_vector", "expr_float", + "expr_integer", "expr_false", "expr_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 IW6CDEBUG + // 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 IW6CDEBUG + 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_) + return true; + else + { +#if IW6CDEBUG + YYCDEBUG << "LAC: initial context established for " + << symbol_name (yytoken) << '\n'; +#endif + yy_lac_established_ = true; + return yy_lac_check_ (yytoken); + } + } + + // Discard any previous initial lookahead context. + void + parser::yy_lac_discard_ (const char* event) + { + /* 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 " + << event << '\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_ = -281; + + const short parser::yytable_ninf_ = -220; + + const short + parser::yypact_[] = + { + 4, -281, -281, -72, -72, -41, -281, -281, 32, 4, + -281, -281, -281, -281, -281, -281, -21, -281, -281, -28, + -1, -22, -281, -281, -281, -281, -43, 1235, -281, -281, + -281, 5, -29, -281, -281, -26, -24, -281, 8, -281, + -281, -281, -281, -281, -281, -281, 1235, 1109, -43, 1235, + 1235, 612, 1, 47, -281, -281, -281, 2111, -281, -281, + -281, -281, -281, -281, 108, 145, -281, -281, -281, -281, + 372, 438, -281, -281, 633, -281, -281, -281, 664, 818, + 982, 987, -281, -281, 39, 59, -281, -281, -281, -281, + -281, -281, -281, 61, 16, -43, 65, 78, 79, 103, + 109, 127, 133, 1443, 1109, -281, 2194, 125, 136, -281, + -281, -281, 1235, 134, -281, -281, -281, -281, 372, 438, + -281, 1132, -281, -281, -281, -281, 39, 137, -281, -281, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1298, + -35, -281, -281, 147, 1235, -43, -281, 951, -281, -281, + 1235, 1235, -43, 1235, 1235, -43, 1235, -281, 1235, 1231, + 1235, -281, 1609, 1235, 102, -43, 2076, -51, -51, 2225, + 865, 2276, 2276, -27, -27, -27, -27, 2235, 273, 2266, + 51, 51, -281, -281, -281, 1294, -281, -281, -281, 23, + -281, 150, 77, 1235, 148, 157, 1381, 160, 162, 163, + 166, -15, 158, 165, 167, 1172, 168, 172, 173, -281, + 409, 703, 703, -281, -281, 1027, -281, -281, -281, -281, + -281, -281, -281, -281, -281, -281, -281, -281, -281, -281, + -281, -281, -281, -281, -281, -281, -281, -281, -281, -281, + -281, 175, 184, 185, 186, 187, 142, -281, -281, 808, + 147, 1921, 30, 176, 1961, 36, 182, 2001, 2040, 195, + 2194, 1231, 150, 1235, -281, -281, 1235, -281, -281, 1080, + 2146, -281, 1235, 224, 1235, 738, -43, 1235, 151, 193, + 196, -281, -281, -281, -281, 2181, -281, 1235, 1235, 1298, + 35, -281, 112, 123, -4, 1132, 1132, -281, -281, -281, + -281, -281, -281, -281, 1235, 204, 206, 209, 210, -281, + -281, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, + 1235, 1235, 207, -281, 1235, 211, -281, 1235, 212, 1235, + 214, 2194, 76, -281, -281, -281, 1643, 215, 1677, 201, + -281, -281, -281, 1407, -8, 1711, -281, -281, -281, 82, + 85, -281, 703, 2194, 1235, 1235, 1235, 1235, 2194, 2194, + 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 2194, 219, + 104, 220, 107, 221, 1745, 1235, -281, 1381, 1235, 1381, + 1235, 1235, -43, 16, 216, 222, -281, 1779, 1487, 1531, + 1575, 1235, -281, 1235, -281, 1235, -281, 120, 249, 1813, + -281, 2194, 223, 1847, 246, -281, -281, -281, 227, 229, + 1235, 232, 1235, 235, 1235, 124, 126, 138, -281, 1381, + 236, 738, 1381, 1235, -281, -281, 228, -281, 230, -281, + 247, -281, -281, -281, -281, -281, 250, -281, 1881, 242, + 243, 248, 1381, 1381, -281, -281, -281, -281, -281 + }; + + const unsigned char + parser::yydefact_[] = + { + 3, 12, 13, 0, 0, 0, 218, 217, 0, 2, + 7, 8, 9, 14, 15, 16, 0, 220, 219, 0, + 0, 0, 1, 4, 5, 6, 181, 0, 10, 11, + 222, 0, 0, 180, 215, 0, 0, 207, 0, 229, + 228, 209, 210, 211, 212, 213, 0, 183, 0, 0, + 0, 0, 0, 217, 221, 225, 227, 0, 90, 91, + 92, 130, 131, 132, 133, 134, 164, 165, 135, 136, + 137, 138, 139, 140, 0, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 0, 151, 152, 153, 154, + 155, 156, 157, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 208, 185, 0, 182, 186, + 163, 158, 0, 0, 224, 226, 198, 199, 161, 162, + 160, 0, 202, 203, 204, 205, 159, 0, 214, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 166, 167, 0, 183, 0, 17, 0, 19, 179, + 0, 183, 0, 0, 183, 0, 0, 197, 0, 185, + 0, 178, 0, 0, 0, 0, 0, 123, 124, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 125, 126, 127, 128, 129, 0, 196, 216, 195, 0, + 182, 187, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, + 0, 0, 0, 44, 49, 0, 45, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 0, 0, 0, 198, 199, 0, 200, 201, 0, + 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 184, 0, 0, 0, 194, 168, 183, 51, 47, 0, + 0, 71, 0, 0, 0, 57, 0, 0, 0, 0, + 0, 82, 83, 84, 86, 0, 87, 183, 183, 0, + 0, 190, 200, 201, 206, 107, 109, 52, 48, 60, + 61, 62, 58, 59, 0, 0, 0, 0, 0, 108, + 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 170, 183, 0, 172, 183, 0, 0, + 0, 111, 0, 50, 46, 66, 0, 0, 0, 0, + 54, 55, 56, 0, 0, 0, 81, 80, 85, 0, + 0, 188, 0, 95, 0, 0, 0, 0, 96, 102, + 103, 104, 105, 106, 97, 98, 99, 101, 100, 0, + 0, 0, 0, 0, 0, 183, 169, 0, 0, 0, + 94, 0, 0, 0, 0, 0, 189, 0, 0, 0, + 0, 183, 171, 183, 173, 183, 223, 0, 72, 0, + 74, 93, 0, 0, 0, 79, 88, 89, 0, 0, + 183, 0, 183, 0, 183, 0, 0, 0, 174, 0, + 0, 57, 0, 0, 63, 65, 182, 68, 182, 70, + 182, 175, 176, 177, 73, 75, 0, 77, 0, 0, + 0, 0, 0, 0, 64, 67, 69, 76, 78 + }; + + const short + parser::yypgoto_[] = + { + -281, -281, -281, 272, 298, 299, -281, -281, -281, 194, + 86, -281, -281, -281, -92, -121, -281, -281, -281, -281, + -281, -281, -281, -281, -281, -281, -281, -281, -281, -281, + -281, -281, -281, -281, -281, -281, -281, -281, -281, 188, + -281, -280, -279, -278, -281, -281, -281, -281, -281, -281, + 92, 203, -66, -62, -281, -281, -127, -46, -281, -281, + -281, -13, 213, 337, -281, 289, 385, -281, -281, -281, + 392, 480, 512, 519, -281, -281, -281, 0, 10, -281, + -17, -281, -281, 130, -281, -281 + }; + + const short + parser::yydefgoto_[] = + { + 0, 8, 9, 10, 11, 12, 13, 14, 15, 223, + 224, 279, 225, 226, 227, 349, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 106, + 412, 251, 252, 253, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 32, 107, 200, 69, 256, + 300, 301, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 198, 84, 85, 86, + 87, 88, 89, 90, 91, 92 + }; + + const short + parser::yytable_[] = + { + 16, 108, 158, 6, 31, 350, 351, 352, 151, 16, + 21, 196, 152, 19, 20, 1, 2, 3, 4, 5, + 6, 391, 6, 94, 17, 18, 33, 199, 95, 96, + 26, 99, 22, 28, 262, 97, 100, 265, 131, 132, + 144, 145, 146, 147, 148, 98, 101, 154, 109, 392, + 6, 126, -193, -193, 7, 151, 27, 93, 108, 152, + 29, 127, 197, 102, 144, 145, 146, 147, 148, 157, + 17, 53, 17, 53, 153, 275, 30, 288, -206, -206, + 170, -206, 333, 30, 127, -206, 56, 170, 336, 277, + 154, 361, 362, 170, -206, 159, 203, -206, 128, 204, + 205, 7, 206, 207, 208, 209, -219, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 35, 36, 155, 38, + 160, 153, 156, 6, 42, 43, 44, 45, 386, 161, + 157, 127, 220, 170, 394, -206, -206, 395, 162, 170, + 221, 222, 170, 116, 146, 147, 148, -198, -198, 342, + -198, 350, 351, 352, -198, 201, 402, 260, 163, 404, + 164, 170, 263, -198, 170, 266, -198, 127, -191, -191, + 359, 360, 428, 17, 53, 272, 441, 170, 442, -192, + -192, 170, 170, 170, -199, -199, 165, -199, 166, 173, + 443, -199, 171, 151, 289, 170, 175, 152, 154, 197, + -199, 276, 260, -199, -198, -198, 260, 380, 282, 281, + 382, 284, 127, 285, 286, 57, 127, 287, 291, 314, + 304, 260, 260, 297, 298, 260, 292, 334, 293, 296, + 127, 127, 127, 337, 103, 127, 309, 110, 111, 151, + 151, -199, -199, 152, 152, 310, 311, 312, 313, 254, + 347, 340, 115, 356, 117, 364, 357, 365, 407, 153, + 366, 367, 390, 379, 118, 385, 388, 381, 383, 127, + 401, 403, 405, 429, 425, 433, 426, 416, 427, 260, + 449, 23, 450, 417, 431, 260, 354, 151, 434, 127, + 435, 152, 169, 437, 254, 127, 439, 445, 254, 451, + 172, 415, 452, 454, 455, 153, 153, 24, 25, 456, + 446, 308, 116, 116, 116, 127, 127, 254, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 131, 132, + 120, 290, 135, 136, 137, 138, 139, 140, 261, 396, + 0, 264, 0, 153, 267, 0, 268, 0, 270, 0, + 255, 271, 304, 127, 144, 145, 146, 147, 148, 0, + 257, 254, 127, 0, 436, 0, 438, 116, 440, 0, + 0, 0, 0, 0, 0, 0, 0, 260, 119, 260, + 0, 280, 414, 0, 0, 0, 278, 127, 0, 127, + 283, 0, 0, 295, 0, 255, 0, 0, 0, 255, + 0, -200, -200, 0, -200, 257, 0, 0, -200, 257, + 0, 0, 0, 117, 117, 117, 0, -200, 255, 260, + -200, 260, 260, 302, 257, 257, 121, 0, 257, 127, + 0, 127, 127, 122, 0, 0, 0, 0, 35, 36, + 0, 38, 260, 260, 116, 6, 42, 43, 44, 45, + 0, 341, 127, 127, 299, 0, 0, 0, -200, -200, + 346, 0, 348, 344, 0, 355, 0, -201, -201, 254, + -201, 254, 255, 0, -201, 0, 0, 271, 117, 0, + 0, 0, 257, -201, 258, 0, -201, 0, 257, 0, + 0, 0, 363, 0, 0, 17, 53, 0, 0, 368, + 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, + 0, 254, 0, 116, 254, 0, 0, 384, 0, 0, + 0, 123, 0, 0, -201, -201, 0, 0, 0, 258, + 0, 0, 259, 258, 254, 254, 0, 0, 0, 122, + 0, 0, 397, 398, 399, 400, 0, 303, 258, 258, + 0, 0, 258, 124, 0, 117, 0, 0, 0, 0, + 125, 0, 0, 0, 0, 302, 409, 0, 411, 413, + 0, 408, 0, 410, 0, 0, 0, 259, 0, 0, + 255, 259, 255, 0, 122, 0, 0, 0, 122, 0, + 257, 0, 257, 0, 0, 121, 305, 306, 0, 0, + 259, 0, 122, 122, 122, 0, 258, 122, 0, 0, + 0, 448, 258, 444, 0, 0, 447, 0, 0, 0, + 0, 0, 255, 0, 117, 255, 0, 123, 0, 0, + 0, 0, 257, 0, 257, 257, 457, 458, 0, 0, + 0, 35, 36, 0, 38, 255, 255, 0, 6, 42, + 43, 44, 45, 112, 259, 257, 257, 113, 0, 124, + 353, 122, 35, 36, 0, 38, 125, 122, 0, 6, + 0, 0, 123, 0, 0, 0, 123, 0, 149, 0, + 0, 150, 0, 0, 0, 0, 0, 0, 0, 303, + 123, 123, 123, -202, -202, 123, -202, 0, 17, 53, + -202, 0, 114, 115, 124, 0, 0, 0, 124, -202, + 0, 125, -202, 0, 258, 125, 258, 0, 0, 17, + 53, 0, 124, 124, 124, 0, 0, 124, 0, 125, + 125, 125, 35, 36, 125, 38, 0, 121, 0, 6, + 42, 43, 44, 45, 122, 0, 0, 0, 113, 123, + -202, -202, 0, 0, 0, 123, 258, 0, 258, 258, + 0, 0, 259, 0, 259, 0, 0, 35, 36, 122, + 38, 122, 0, 0, 6, 42, 43, 44, 45, 258, + 258, 124, 0, 220, 0, 0, 0, 124, 125, 17, + 53, 221, 222, 0, 125, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 259, 0, 353, 259, 0, 0, + 0, 122, 0, 122, 122, 315, 316, 0, 317, 318, + 0, 0, 0, 0, 17, 53, 0, 259, 259, 0, + 0, 0, 123, 0, 122, 122, 0, 35, 36, 0, + 38, 0, 0, 0, 6, 0, 0, -203, -203, 0, + -203, 0, 0, 149, -203, 0, 174, 123, 0, 123, + 0, 319, 320, -203, 124, 0, -203, 0, 0, 0, + 0, 125, 0, 0, 0, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 0, 0, 124, + 0, 124, 0, 0, 17, 53, 125, 0, 125, 123, + 0, 123, 123, 0, -203, -203, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 131, 132, 123, 123, 135, 136, 137, 138, 139, 140, + 0, 124, 0, 124, 124, 0, 0, 0, 125, 0, + 125, 125, 0, 141, 142, 143, 144, 145, 146, 147, + 148, 0, 202, 0, 124, 124, 0, 0, 0, 0, + 203, 125, 125, 204, 205, 0, 206, 207, 208, 209, + 0, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 35, 36, 0, 38, 0, 0, 0, 6, 42, 43, + 44, 45, 0, 0, 157, 219, 220, 0, 0, 0, + 0, 0, 0, 0, 221, 222, 0, 0, 0, 0, + 0, -204, -204, 0, -204, 0, -205, -205, -204, -205, + 0, 0, 0, -205, 0, 0, 0, -204, 202, 0, + -204, 0, -205, 0, 0, -205, 203, 17, 53, 204, + 205, 0, 206, 207, 208, 209, 0, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 35, 36, 0, 38, + 0, 0, 0, 6, 42, 43, 44, 45, -204, -204, + 157, 307, 220, -205, -205, 0, 0, 0, 0, 0, + 221, 222, 343, 0, 0, 0, 0, 0, 0, 203, + 0, 0, 204, 205, 0, 206, 207, 208, 209, 0, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 35, + 36, 0, 38, 17, 53, 34, 6, 42, 43, 44, + 45, 0, 0, 157, 0, 220, 0, 0, 0, 0, + 0, 0, 0, 221, 222, 0, 0, 0, 35, 36, + 37, 38, 39, 40, 41, 6, 42, 43, 44, 45, + 46, 0, 0, 0, 104, 105, 0, 0, 48, 0, + 0, 35, 36, 0, 38, 0, 17, 53, 6, 0, + 0, 0, 0, 0, 49, 50, 0, 149, 34, 0, + 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 51, 0, 0, 52, 17, 53, 30, 54, 55, + 56, 35, 36, 37, 38, 39, 40, 41, 6, 42, + 43, 44, 45, 46, 0, 0, 0, 47, 17, 53, + 0, 48, 0, 294, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 50, 0, + 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 51, 0, 0, 52, 17, 53, + 30, 54, 55, 56, 35, 36, 37, 38, 39, 40, + 41, 6, 42, 43, 44, 45, 46, 269, 0, 0, + 47, 0, 0, 130, 48, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 49, 50, 0, 0, 34, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 51, 0, 0, + 52, 17, 53, 30, 54, 55, 56, 35, 36, 37, + 38, 39, 40, 41, 6, 42, 43, 44, 45, 46, + 274, 0, 0, 104, 0, 0, 130, 48, 0, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 0, + 0, 0, 0, 49, 50, 0, 0, 0, 0, 0, + 0, 0, 141, 142, 143, 144, 145, 146, 147, 148, + 51, 0, 0, 52, 17, 53, 30, 54, 55, 56, + 203, 0, 0, 204, 205, 0, 206, 207, 208, 209, + 0, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 35, 36, 0, 38, 0, 0, 0, 6, 42, 43, + 44, 45, 0, 0, 157, 0, 220, 0, 0, 0, + 0, 0, 0, 0, 221, 222, 35, 36, 0, 38, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 149, 0, 0, 174, 0, 0, 0, 0, + 319, 320, 0, 0, 0, 0, 0, 17, 53, 0, + 0, 0, 0, 0, 321, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, 167, 0, 0, 0, 0, + 168, 0, 0, 17, 53, 130, 0, 0, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 142, 143, 144, 145, 146, 147, 148, 419, + 0, 0, 0, 0, 420, 0, 0, 0, 0, 130, + 0, 0, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 141, 142, 143, 144, 145, + 146, 147, 148, 421, 0, 0, 0, 0, 422, 0, + 0, 0, 0, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 423, 0, 0, + 0, 0, 424, 0, 0, 0, 0, 130, 0, 0, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 167, 0, 141, 142, 143, 144, 145, 146, 147, + 148, 130, 0, 0, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 387, 0, 141, 142, 143, + 144, 145, 146, 147, 148, 130, 0, 0, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 389, + 0, 141, 142, 143, 144, 145, 146, 147, 148, 130, + 0, 0, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 393, 0, 141, 142, 143, 144, 145, + 146, 147, 148, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 406, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 130, 0, 0, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 418, 0, 141, 142, 143, 144, 145, 146, 147, + 148, 130, 0, 0, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 430, 0, 141, 142, 143, + 144, 145, 146, 147, 148, 130, 0, 0, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 432, + 0, 141, 142, 143, 144, 145, 146, 147, 148, 130, + 0, 0, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 453, 0, 141, 142, 143, 144, 145, + 146, 147, 148, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 332, 0, 0, + 0, 0, 0, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 335, 0, 0, + 0, 0, 0, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 338, 0, 0, + 0, 0, 0, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 339, 0, 0, + 0, 0, 130, 0, 0, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 141, 142, + 143, 144, 145, 146, 147, 148, 273, 0, 130, 0, + 0, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 142, 143, 144, 145, 146, + 147, 148, 129, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 345, 130, 0, + 0, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 142, 143, 144, 145, 146, + 147, 148, 358, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 130, 0, 0, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 0, 0, 0, + 0, 0, 141, 142, 143, 144, 145, 146, 147, 148, + 131, 132, 0, 134, 135, 136, 137, 138, 139, 140, + 131, 132, 0, 0, 135, 136, 137, 138, 139, 140, + 0, 0, 0, 141, 142, 143, 144, 145, 146, 147, + 148, 0, 0, 0, 142, 143, 144, 145, 146, 147, + 148, 131, 132, 0, 0, 135, 136, 137, 138, 139, + 140, 131, 132, 0, 0, 0, 0, 137, 138, 139, + 140, 0, 0, 0, 0, 142, 0, 144, 145, 146, + 147, 148, 0, 0, 0, 0, 0, 144, 145, 146, + 147, 148 + }; + + const short + parser::yycheck_[] = + { + 0, 47, 94, 46, 21, 285, 285, 285, 74, 9, + 51, 46, 74, 3, 4, 11, 12, 13, 14, 15, + 46, 29, 46, 52, 96, 97, 26, 154, 57, 55, + 51, 55, 0, 61, 161, 35, 36, 164, 65, 66, + 91, 92, 93, 94, 95, 35, 36, 51, 48, 57, + 46, 51, 56, 57, 97, 121, 77, 52, 104, 121, + 61, 51, 97, 55, 91, 92, 93, 94, 95, 53, + 96, 97, 96, 97, 74, 52, 98, 92, 39, 40, + 57, 42, 52, 98, 74, 46, 101, 57, 52, 12, + 51, 56, 57, 57, 55, 95, 19, 58, 97, 22, + 23, 97, 25, 26, 27, 28, 59, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 59, 42, + 55, 121, 61, 46, 47, 48, 49, 50, 52, 51, + 53, 121, 55, 57, 52, 96, 97, 52, 59, 57, + 63, 64, 57, 51, 93, 94, 95, 39, 40, 276, + 42, 431, 431, 431, 46, 155, 52, 157, 55, 52, + 51, 57, 162, 55, 57, 165, 58, 157, 56, 57, + 297, 298, 52, 96, 97, 175, 52, 57, 52, 56, + 57, 57, 57, 57, 39, 40, 59, 42, 55, 55, + 52, 46, 56, 259, 211, 57, 59, 259, 51, 97, + 55, 51, 202, 58, 96, 97, 206, 334, 51, 61, + 337, 51, 202, 51, 51, 27, 206, 51, 60, 77, + 220, 221, 222, 51, 51, 225, 61, 51, 61, 61, + 220, 221, 222, 51, 46, 225, 61, 49, 50, 305, + 306, 96, 97, 305, 306, 61, 61, 61, 61, 157, + 26, 56, 101, 60, 51, 51, 60, 51, 385, 259, + 51, 51, 61, 56, 51, 51, 51, 56, 56, 259, + 51, 51, 51, 24, 401, 29, 403, 61, 405, 279, + 52, 9, 52, 61, 61, 285, 286, 353, 61, 279, + 61, 353, 104, 61, 202, 285, 61, 61, 206, 52, + 112, 393, 52, 61, 61, 305, 306, 9, 9, 61, + 431, 225, 220, 221, 222, 305, 306, 225, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 65, 66, + 51, 211, 69, 70, 71, 72, 73, 74, 160, 362, + -1, 163, -1, 353, 166, -1, 168, -1, 170, -1, + 157, 173, 362, 353, 91, 92, 93, 94, 95, -1, + 157, 279, 362, -1, 420, -1, 422, 285, 424, -1, + -1, -1, -1, -1, -1, -1, -1, 387, 51, 389, + -1, 203, 392, -1, -1, -1, 202, 387, -1, 389, + 206, -1, -1, 215, -1, 202, -1, -1, -1, 206, + -1, 39, 40, -1, 42, 202, -1, -1, 46, 206, + -1, -1, -1, 220, 221, 222, -1, 55, 225, 429, + 58, 431, 432, 220, 221, 222, 51, -1, 225, 429, + -1, 431, 432, 51, -1, -1, -1, -1, 39, 40, + -1, 42, 452, 453, 362, 46, 47, 48, 49, 50, + -1, 273, 452, 453, 55, -1, -1, -1, 96, 97, + 282, -1, 284, 279, -1, 287, -1, 39, 40, 387, + 42, 389, 279, -1, 46, -1, -1, 299, 285, -1, + -1, -1, 279, 55, 157, -1, 58, -1, 285, -1, + -1, -1, 314, -1, -1, 96, 97, -1, -1, 321, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + -1, 429, -1, 431, 432, -1, -1, 339, -1, -1, + -1, 51, -1, -1, 96, 97, -1, -1, -1, 202, + -1, -1, 157, 206, 452, 453, -1, -1, -1, 157, + -1, -1, 364, 365, 366, 367, -1, 220, 221, 222, + -1, -1, 225, 51, -1, 362, -1, -1, -1, -1, + 51, -1, -1, -1, -1, 362, 388, -1, 390, 391, + -1, 387, -1, 389, -1, -1, -1, 202, -1, -1, + 387, 206, 389, -1, 202, -1, -1, -1, 206, -1, + 387, -1, 389, -1, -1, 220, 221, 222, -1, -1, + 225, -1, 220, 221, 222, -1, 279, 225, -1, -1, + -1, 433, 285, 429, -1, -1, 432, -1, -1, -1, + -1, -1, 429, -1, 431, 432, -1, 157, -1, -1, + -1, -1, 429, -1, 431, 432, 452, 453, -1, -1, + -1, 39, 40, -1, 42, 452, 453, -1, 46, 47, + 48, 49, 50, 51, 279, 452, 453, 55, -1, 157, + 285, 279, 39, 40, -1, 42, 157, 285, -1, 46, + -1, -1, 202, -1, -1, -1, 206, -1, 55, -1, + -1, 58, -1, -1, -1, -1, -1, -1, -1, 362, + 220, 221, 222, 39, 40, 225, 42, -1, 96, 97, + 46, -1, 100, 101, 202, -1, -1, -1, 206, 55, + -1, 202, 58, -1, 387, 206, 389, -1, -1, 96, + 97, -1, 220, 221, 222, -1, -1, 225, -1, 220, + 221, 222, 39, 40, 225, 42, -1, 362, -1, 46, + 47, 48, 49, 50, 362, -1, -1, -1, 55, 279, + 96, 97, -1, -1, -1, 285, 429, -1, 431, 432, + -1, -1, 387, -1, 389, -1, -1, 39, 40, 387, + 42, 389, -1, -1, 46, 47, 48, 49, 50, 452, + 453, 279, -1, 55, -1, -1, -1, 285, 279, 96, + 97, 63, 64, -1, 285, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 429, -1, 431, 432, -1, -1, + -1, 429, -1, 431, 432, 17, 18, -1, 20, 21, + -1, -1, -1, -1, 96, 97, -1, 452, 453, -1, + -1, -1, 362, -1, 452, 453, -1, 39, 40, -1, + 42, -1, -1, -1, 46, -1, -1, 39, 40, -1, + 42, -1, -1, 55, 46, -1, 58, 387, -1, 389, + -1, 63, 64, 55, 362, -1, 58, -1, -1, -1, + -1, 362, -1, -1, -1, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, -1, -1, 387, + -1, 389, -1, -1, 96, 97, 387, -1, 389, 429, + -1, 431, 432, -1, 96, 97, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 452, 453, 69, 70, 71, 72, 73, 74, + -1, 429, -1, 431, 432, -1, -1, -1, 429, -1, + 431, 432, -1, 88, 89, 90, 91, 92, 93, 94, + 95, -1, 11, -1, 452, 453, -1, -1, -1, -1, + 19, 452, 453, 22, 23, -1, 25, 26, 27, 28, + -1, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, -1, 42, -1, -1, -1, 46, 47, 48, + 49, 50, -1, -1, 53, 54, 55, -1, -1, -1, + -1, -1, -1, -1, 63, 64, -1, -1, -1, -1, + -1, 39, 40, -1, 42, -1, 39, 40, 46, 42, + -1, -1, -1, 46, -1, -1, -1, 55, 11, -1, + 58, -1, 55, -1, -1, 58, 19, 96, 97, 22, + 23, -1, 25, 26, 27, 28, -1, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, -1, 42, + -1, -1, -1, 46, 47, 48, 49, 50, 96, 97, + 53, 54, 55, 96, 97, -1, -1, -1, -1, -1, + 63, 64, 12, -1, -1, -1, -1, -1, -1, 19, + -1, -1, 22, 23, -1, 25, 26, 27, 28, -1, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, -1, 42, 96, 97, 16, 46, 47, 48, 49, + 50, -1, -1, 53, -1, 55, -1, -1, -1, -1, + -1, -1, -1, 63, 64, -1, -1, -1, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, -1, -1, -1, 55, 56, -1, -1, 59, -1, + -1, 39, 40, -1, 42, -1, 96, 97, 46, -1, + -1, -1, -1, -1, 75, 76, -1, 55, 16, -1, + 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 92, -1, -1, 95, 96, 97, 98, 99, 100, + 101, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, -1, -1, -1, 55, 96, 97, + -1, 59, -1, 61, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 75, 76, -1, + -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 92, -1, -1, 95, 96, 97, + 98, 99, 100, 101, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 56, -1, -1, + 55, -1, -1, 62, 59, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + 75, 76, -1, -1, 16, -1, -1, -1, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 92, -1, -1, + 95, 96, 97, 98, 99, 100, 101, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 56, -1, -1, 55, -1, -1, 62, 59, -1, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, -1, + -1, -1, -1, 75, 76, -1, -1, -1, -1, -1, + -1, -1, 88, 89, 90, 91, 92, 93, 94, 95, + 92, -1, -1, 95, 96, 97, 98, 99, 100, 101, + 19, -1, -1, 22, 23, -1, 25, 26, 27, 28, + -1, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, -1, 42, -1, -1, -1, 46, 47, 48, + 49, 50, -1, -1, 53, -1, 55, -1, -1, -1, + -1, -1, -1, -1, 63, 64, 39, 40, -1, 42, + -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, + -1, -1, 55, -1, -1, 58, -1, -1, -1, -1, + 63, 64, -1, -1, -1, -1, -1, 96, 97, -1, + -1, -1, -1, -1, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 52, -1, -1, -1, -1, + 57, -1, -1, 96, 97, 62, -1, -1, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 88, 89, 90, 91, 92, 93, 94, 95, 52, + -1, -1, -1, -1, 57, -1, -1, -1, -1, 62, + -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 88, 89, 90, 91, 92, + 93, 94, 95, 52, -1, -1, -1, -1, 57, -1, + -1, -1, -1, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 52, -1, -1, + -1, -1, 57, -1, -1, -1, -1, 62, -1, -1, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 52, -1, 88, 89, 90, 91, 92, 93, 94, + 95, 62, -1, -1, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 52, -1, 88, 89, 90, + 91, 92, 93, 94, 95, 62, -1, -1, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, + -1, 88, 89, 90, 91, 92, 93, 94, 95, 62, + -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 52, -1, 88, 89, 90, 91, 92, + 93, 94, 95, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 52, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 62, -1, -1, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 52, -1, 88, 89, 90, 91, 92, 93, 94, + 95, 62, -1, -1, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 52, -1, 88, 89, 90, + 91, 92, 93, 94, 95, 62, -1, -1, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, + -1, 88, 89, 90, 91, 92, 93, 94, 95, 62, + -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 52, -1, 88, 89, 90, 91, 92, + 93, 94, 95, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 56, -1, -1, + -1, -1, -1, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 56, -1, -1, + -1, -1, -1, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 56, -1, -1, + -1, -1, -1, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 57, -1, -1, + -1, -1, 62, -1, -1, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 88, 89, + 90, 91, 92, 93, 94, 95, 60, -1, 62, -1, + -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 88, 89, 90, 91, 92, 93, + 94, 95, 61, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, + 89, 90, 91, 92, 93, 94, 95, 61, 62, -1, + -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 88, 89, 90, 91, 92, 93, + 94, 95, 61, 62, -1, -1, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 62, -1, -1, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 88, + 89, 90, 91, 92, 93, 94, 95, -1, -1, -1, + -1, -1, 88, 89, 90, 91, 92, 93, 94, 95, + 65, 66, -1, 68, 69, 70, 71, 72, 73, 74, + 65, 66, -1, -1, 69, 70, 71, 72, 73, 74, + -1, -1, -1, 88, 89, 90, 91, 92, 93, 94, + 95, -1, -1, -1, 89, 90, 91, 92, 93, 94, + 95, 65, 66, -1, -1, 69, 70, 71, 72, 73, + 74, 65, 66, -1, -1, -1, -1, 71, 72, 73, + 74, -1, -1, -1, -1, 89, -1, 91, 92, 93, + 94, 95, -1, -1, -1, -1, -1, 91, 92, 93, + 94, 95 + }; + + const unsigned char + parser::yystos_[] = + { + 0, 11, 12, 13, 14, 15, 46, 97, 113, 114, + 115, 116, 117, 118, 119, 120, 189, 96, 97, 190, + 190, 51, 0, 115, 116, 117, 51, 77, 61, 61, + 98, 192, 167, 189, 16, 39, 40, 41, 42, 43, + 44, 45, 47, 48, 49, 50, 51, 55, 59, 75, + 76, 92, 95, 97, 99, 100, 101, 151, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 170, + 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 52, 52, 57, 55, 189, 190, 55, + 189, 190, 55, 151, 55, 56, 151, 168, 169, 189, + 151, 151, 51, 55, 100, 101, 162, 163, 174, 175, + 177, 178, 182, 183, 184, 185, 189, 190, 97, 61, + 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 88, 89, 90, 91, 92, 93, 94, 95, 55, + 58, 164, 165, 189, 51, 59, 61, 53, 126, 189, + 55, 51, 59, 55, 51, 59, 55, 52, 57, 151, + 57, 56, 151, 55, 58, 59, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 46, 97, 188, 168, + 169, 189, 11, 19, 22, 23, 25, 26, 27, 28, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 54, + 55, 63, 64, 121, 122, 124, 125, 126, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 153, 154, 155, 162, 163, 171, 174, 175, 178, + 189, 151, 168, 189, 151, 168, 189, 151, 151, 56, + 151, 151, 189, 60, 56, 52, 51, 12, 121, 123, + 151, 61, 51, 121, 51, 51, 51, 51, 92, 192, + 195, 60, 61, 61, 61, 151, 61, 51, 51, 55, + 172, 173, 174, 175, 189, 178, 178, 54, 122, 61, + 61, 61, 61, 61, 77, 17, 18, 20, 21, 63, + 64, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 56, 52, 51, 56, 52, 51, 56, 57, + 56, 151, 168, 12, 121, 61, 151, 26, 151, 127, + 153, 154, 155, 178, 189, 151, 60, 60, 61, 168, + 168, 56, 57, 151, 51, 51, 51, 51, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 56, + 168, 56, 168, 56, 151, 51, 52, 52, 51, 52, + 61, 29, 57, 52, 52, 52, 173, 151, 151, 151, + 151, 51, 52, 51, 52, 51, 52, 168, 121, 151, + 121, 151, 152, 151, 189, 126, 61, 61, 52, 52, + 57, 52, 57, 52, 57, 168, 168, 168, 52, 24, + 52, 61, 52, 29, 61, 61, 169, 61, 169, 61, + 169, 52, 52, 52, 121, 61, 127, 121, 151, 52, + 52, 52, 52, 52, 61, 61, 61, 121, 121 + }; + + const unsigned char + parser::yyr1_[] = + { + 0, 112, 113, 113, 114, 114, 114, 114, 114, 114, + 115, 116, 117, 117, 117, 117, 117, 118, 119, 120, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 122, 122, 123, 123, 124, 124, + 125, 125, 126, 126, 127, 127, 127, 127, 128, 128, + 129, 129, 129, 130, 131, 131, 132, 133, 133, 134, + 134, 135, 136, 137, 138, 139, 140, 141, 141, 142, + 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, + 151, 151, 151, 152, 152, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 154, 154, 155, + 155, 156, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 159, 160, + 160, 160, 160, 161, 162, 162, 163, 163, 164, 164, + 164, 164, 164, 164, 165, 165, 165, 165, 166, 167, + 167, 167, 168, 168, 169, 169, 170, 170, 171, 172, + 172, 173, 173, 173, 174, 175, 176, 177, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 189, 190, + 190, 191, 192, 193, 194, 194, 195, 195, 196, 197 + }; + + const signed char + parser::yyr2_[] = + { + 0, 2, 1, 0, 2, 2, 2, 1, 1, 1, + 3, 3, 1, 1, 1, 1, 1, 5, 4, 5, + 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, 1, 2, 1, + 3, 2, 3, 2, 1, 1, 1, 0, 2, 2, + 2, 2, 2, 6, 8, 6, 3, 8, 6, 8, + 6, 2, 5, 7, 5, 7, 9, 7, 9, 5, + 3, 3, 2, 2, 2, 3, 2, 2, 5, 5, + 1, 1, 1, 1, 0, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, + 2, 5, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 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, 2, 2, 1, 1, 2, 2, 4, 6, + 5, 7, 5, 7, 8, 9, 9, 9, 3, 3, + 1, 0, 1, 0, 3, 1, 2, 3, 3, 3, + 1, 1, 1, 1, 4, 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 7, 2, 1, 2, 1, 1, 1 + }; + + + + +#if IW6CDEBUG + const short + parser::yyrline_[] = + { + 0, 261, 261, 262, 266, 268, 270, 272, 274, 276, + 281, 285, 290, 291, 292, 293, 294, 298, 303, 308, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 340, 341, 345, 347, 352, 354, + 359, 360, 364, 365, 369, 371, 373, 376, 380, 382, + 387, 389, 391, 396, 401, 403, 408, 413, 415, 420, + 422, 427, 432, 437, 442, 447, 452, 457, 459, 464, + 469, 471, 476, 481, 486, 491, 493, 498, 503, 508, + 513, 514, 515, 519, 520, 524, 526, 528, 530, 532, + 534, 536, 538, 540, 542, 544, 546, 551, 553, 558, + 560, 565, 570, 572, 574, 576, 578, 580, 582, 584, + 586, 588, 590, 592, 594, 596, 598, 600, 602, 604, + 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, + 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, + 629, 630, 631, 632, 633, 634, 635, 636, 640, 645, + 647, 649, 651, 656, 661, 662, 665, 666, 670, 672, + 674, 676, 678, 680, 685, 687, 689, 691, 696, 701, + 703, 706, 710, 713, 717, 719, 724, 726, 731, 736, + 738, 743, 744, 745, 749, 754, 759, 764, 769, 770, + 771, 772, 773, 774, 775, 776, 777, 781, 786, 791, + 796, 801, 806, 811, 816, 821, 826, 831, 833, 838, + 840, 845, 850, 855, 860, 862, 867, 869, 874, 879 + }; + + 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 // IW6CDEBUG + + +#line 13 "parser.ypp" +} } } // xsk::gsc::iw6c +#line 4661 "parser.cpp" + +#line 883 "parser.ypp" + + +void xsk::gsc::iw6c::parser::error(const xsk::gsc::location& loc, const std::string& msg) +{ + throw xsk::gsc::comp_error(loc, msg); +} diff --git a/src/experimental/iw6c/xsk/parser.hpp b/src/experimental/iw6c/xsk/parser.hpp new file mode 100644 index 00000000..fd5fecb9 --- /dev/null +++ b/src/experimental/iw6c/xsk/parser.hpp @@ -0,0 +1,5550 @@ +// A Bison parser, made by GNU Bison 3.8.2. + +// 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::iw6c::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_IW6C_PARSER_HPP_INCLUDED +# define YY_IW6C_PARSER_HPP_INCLUDED +// "%code requires" blocks. +#line 28 "parser.ypp" + +#ifdef _MSC_VER +#pragma warning(disable:4065) +#pragma warning(disable:4127) +#endif +#include "iw6c.hpp" +namespace xsk::gsc::iw6c { class lexer; } + +#line 58 "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 IW6C_ASSERT +# include +# define IW6C_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 + +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# 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 IW6CDEBUG +# if defined YYDEBUG +#if YYDEBUG +# define IW6CDEBUG 1 +# else +# define IW6CDEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define IW6CDEBUG 1 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined IW6CDEBUG */ + +#line 13 "parser.ypp" +namespace xsk { namespace gsc { namespace iw6c { +#line 207 "parser.hpp" + + + + + /// A Bison parser. + class parser + { + public: +#ifdef IW6CSTYPE +# ifdef __GNUC__ +# pragma GCC message "bison: do not #define IW6CSTYPE in C++, use %define api.value.type" +# endif + typedef IW6CSTYPE value_type; +#else + /// 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 value_type + { + public: + /// Type of *this. + typedef value_type self_type; + + /// Empty construction. + value_type () YY_NOEXCEPT + : yyraw_ () + , yytypeid_ (YY_NULLPTR) + {} + + /// Construct and fill. + template + value_type (YY_RVREF (T) t) + : yytypeid_ (&typeid (T)) + { + IW6C_ASSERT (sizeof (T) <= size); + new (yyas_ ()) T (YY_MOVE (t)); + } + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + value_type (const self_type&) = delete; + /// Non copyable. + self_type& operator= (const self_type&) = delete; +#endif + + /// Destruction, allowed only if empty. + ~value_type () YY_NOEXCEPT + { + IW6C_ASSERT (!yytypeid_); + } + +# if 201103L <= YY_CPLUSPLUS + /// Instantiate a \a T in here from \a t. + template + T& + emplace (U&&... u) + { + IW6C_ASSERT (!yytypeid_); + IW6C_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 () + { + IW6C_ASSERT (!yytypeid_); + IW6C_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) + { + IW6C_ASSERT (!yytypeid_); + IW6C_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 + { + IW6C_ASSERT (yytypeid_); + IW6C_ASSERT (*yytypeid_ == typeid (T)); + IW6C_ASSERT (sizeof (T) <= size); + return *yyas_ (); + } + + /// Const accessor to a built \a T (for %printer). + template + const T& + as () const YY_NOEXCEPT + { + IW6C_ASSERT (yytypeid_); + IW6C_ASSERT (*yytypeid_ == typeid (T)); + IW6C_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 + { + IW6C_ASSERT (yytypeid_); + IW6C_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. + value_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 = yyraw_; + return static_cast (yyp); + } + + /// Const accessor to raw memory as \a T. + template + const T* + yyas_ () const YY_NOEXCEPT + { + const void *yyp = yyraw_; + return static_cast (yyp); + } + + /// An auxiliary type to compute the largest semantic type. + union union_type + { + // expr_function + // expr_pointer + char dummy1[sizeof (ast::call)]; + + // declaration + char dummy2[sizeof (ast::decl)]; + + // decl_constant + char dummy3[sizeof (ast::decl_constant::ptr)]; + + // decl_thread + char dummy4[sizeof (ast::decl_thread::ptr)]; + + // decl_usingtree + char dummy5[sizeof (ast::decl_usingtree::ptr)]; + + // expr + // expr_or_empty + // expr_assign + // expr_increment + // expr_decrement + // expr_ternary + // expr_binary + // expr_primitive + // expr_tuple + // expr_tuple_types + // expr_object + char dummy6[sizeof (ast::expr)]; + + // expr_add_array + char dummy7[sizeof (ast::expr_add_array::ptr)]; + + // expr_anim + char dummy8[sizeof (ast::expr_anim::ptr)]; + + // expr_animation + char dummy9[sizeof (ast::expr_animation::ptr)]; + + // expr_animtree + char dummy10[sizeof (ast::expr_animtree::ptr)]; + + // expr_arguments + // expr_arguments_no_empty + char dummy11[sizeof (ast::expr_arguments::ptr)]; + + // expr_array + char dummy12[sizeof (ast::expr_array::ptr)]; + + // expr_call + char dummy13[sizeof (ast::expr_call::ptr)]; + + // expr_complement + char dummy14[sizeof (ast::expr_complement::ptr)]; + + // expr_empty_array + char dummy15[sizeof (ast::expr_empty_array::ptr)]; + + // expr_false + char dummy16[sizeof (ast::expr_false::ptr)]; + + // expr_field + char dummy17[sizeof (ast::expr_field::ptr)]; + + // expr_float + char dummy18[sizeof (ast::expr_float::ptr)]; + + // expr_game + char dummy19[sizeof (ast::expr_game::ptr)]; + + // expr_identifier_nosize + // expr_identifier + char dummy20[sizeof (ast::expr_identifier::ptr)]; + + // expr_integer + char dummy21[sizeof (ast::expr_integer::ptr)]; + + // expr_istring + char dummy22[sizeof (ast::expr_istring::ptr)]; + + // expr_level + char dummy23[sizeof (ast::expr_level::ptr)]; + + // expr_method + char dummy24[sizeof (ast::expr_method::ptr)]; + + // expr_negate + char dummy25[sizeof (ast::expr_negate::ptr)]; + + // expr_not + char dummy26[sizeof (ast::expr_not::ptr)]; + + // expr_parameters + char dummy27[sizeof (ast::expr_parameters::ptr)]; + + // expr_paren + char dummy28[sizeof (ast::expr_paren::ptr)]; + + // expr_path + char dummy29[sizeof (ast::expr_path::ptr)]; + + // expr_reference + char dummy30[sizeof (ast::expr_reference::ptr)]; + + // expr_self + char dummy31[sizeof (ast::expr_self::ptr)]; + + // expr_size + char dummy32[sizeof (ast::expr_size::ptr)]; + + // expr_string + char dummy33[sizeof (ast::expr_string::ptr)]; + + // expr_thisthread + char dummy34[sizeof (ast::expr_thisthread::ptr)]; + + // expr_true + char dummy35[sizeof (ast::expr_true::ptr)]; + + // expr_tuple_arguments + char dummy36[sizeof (ast::expr_tuple::ptr)]; + + // expr_undefined + char dummy37[sizeof (ast::expr_undefined::ptr)]; + + // expr_vector + char dummy38[sizeof (ast::expr_vector::ptr)]; + + // include + char dummy39[sizeof (ast::include::ptr)]; + + // program + char dummy40[sizeof (ast::program::ptr)]; + + // stmt + // stmt_or_dev + char dummy41[sizeof (ast::stmt)]; + + // stmt_assign + char dummy42[sizeof (ast::stmt_assign::ptr)]; + + // stmt_break + char dummy43[sizeof (ast::stmt_break::ptr)]; + + // stmt_breakpoint + char dummy44[sizeof (ast::stmt_breakpoint::ptr)]; + + // stmt_call + char dummy45[sizeof (ast::stmt_call::ptr)]; + + // stmt_case + char dummy46[sizeof (ast::stmt_case::ptr)]; + + // stmt_continue + char dummy47[sizeof (ast::stmt_continue::ptr)]; + + // stmt_default + char dummy48[sizeof (ast::stmt_default::ptr)]; + + // stmt_dev + char dummy49[sizeof (ast::stmt_dev::ptr)]; + + // stmt_dowhile + char dummy50[sizeof (ast::stmt_dowhile::ptr)]; + + // stmt_endon + char dummy51[sizeof (ast::stmt_endon::ptr)]; + + // stmt_expr + char dummy52[sizeof (ast::stmt_expr::ptr)]; + + // stmt_for + char dummy53[sizeof (ast::stmt_for::ptr)]; + + // stmt_foreach + char dummy54[sizeof (ast::stmt_foreach::ptr)]; + + // stmt_if + char dummy55[sizeof (ast::stmt_if::ptr)]; + + // stmt_ifelse + char dummy56[sizeof (ast::stmt_ifelse::ptr)]; + + // stmt_list + // stmt_or_dev_list + // stmt_block + char dummy57[sizeof (ast::stmt_list::ptr)]; + + // stmt_notify + char dummy58[sizeof (ast::stmt_notify::ptr)]; + + // stmt_prof_begin + char dummy59[sizeof (ast::stmt_prof_begin::ptr)]; + + // stmt_prof_end + char dummy60[sizeof (ast::stmt_prof_end::ptr)]; + + // stmt_return + char dummy61[sizeof (ast::stmt_return::ptr)]; + + // stmt_switch + char dummy62[sizeof (ast::stmt_switch::ptr)]; + + // stmt_wait + char dummy63[sizeof (ast::stmt_wait::ptr)]; + + // stmt_waittill + char dummy64[sizeof (ast::stmt_waittill::ptr)]; + + // stmt_waittillframeend + char dummy65[sizeof (ast::stmt_waittillframeend::ptr)]; + + // stmt_waittillmatch + char dummy66[sizeof (ast::stmt_waittillmatch::ptr)]; + + // stmt_while + char dummy67[sizeof (ast::stmt_while::ptr)]; + + // "path" + // "identifier" + // "string literal" + // "localized string" + // "float" + // "integer" + char dummy68[sizeof (std::string)]; + }; + + /// 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]; + }; + + /// Whether the content is built: if defined, the name of the stored type. + const std::type_info *yytypeid_; + }; + +#endif + /// Backward compatibility (Bison 3.8). + typedef value_type semantic_type; + + /// 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 + { + IW6CEMPTY = -2, + IW6CEOF = 0, // "end of file" + IW6Cerror = 1, // error + IW6CUNDEF = 2, // "invalid token" + SH_DEFINE = 3, // "#define" + SH_UNDEF = 4, // "#undef" + SH_IFDEF = 5, // "#ifdef" + SH_IFNDEF = 6, // "#ifndef" + SH_IF = 7, // "#if" + SH_ELIF = 8, // "#elif" + SH_ELSE = 9, // "#else" + SH_ENDIF = 10, // "#endif" + DEVBEGIN = 11, // "/#" + DEVEND = 12, // "#/" + INLINE = 13, // "#inline" + INCLUDE = 14, // "#include" + USINGTREE = 15, // "#using_animtree" + ANIMTREE = 16, // "#animtree" + ENDON = 17, // "endon" + NOTIFY = 18, // "notify" + WAIT = 19, // "wait" + WAITTILL = 20, // "waittill" + WAITTILLMATCH = 21, // "waittillmatch" + WAITTILLFRAMEEND = 22, // "waittillframeend" + IF = 23, // "if" + ELSE = 24, // "else" + DO = 25, // "do" + WHILE = 26, // "while" + FOR = 27, // "for" + FOREACH = 28, // "foreach" + IN = 29, // "in" + SWITCH = 30, // "switch" + CASE = 31, // "case" + DEFAULT = 32, // "default" + BREAK = 33, // "break" + CONTINUE = 34, // "continue" + RETURN = 35, // "return" + BREAKPOINT = 36, // "breakpoint" + PROFBEGIN = 37, // "prof_begin" + PROFEND = 38, // "prof_end" + THREAD = 39, // "thread" + CHILDTHREAD = 40, // "childthread" + THISTHREAD = 41, // "thisthread" + CALL = 42, // "call" + TRUE = 43, // "true" + FALSE = 44, // "false" + UNDEFINED = 45, // "undefined" + SIZE = 46, // "size" + GAME = 47, // "game" + SELF = 48, // "self" + ANIM = 49, // "anim" + LEVEL = 50, // "level" + LPAREN = 51, // "(" + RPAREN = 52, // ")" + LBRACE = 53, // "{" + RBRACE = 54, // "}" + LBRACKET = 55, // "[" + RBRACKET = 56, // "]" + COMMA = 57, // "," + DOT = 58, // "." + DOUBLECOLON = 59, // "::" + COLON = 60, // ":" + SEMICOLON = 61, // ";" + QMARK = 62, // "?" + INCREMENT = 63, // "++" + DECREMENT = 64, // "--" + LSHIFT = 65, // "<<" + RSHIFT = 66, // ">>" + OR = 67, // "||" + AND = 68, // "&&" + EQUALITY = 69, // "==" + INEQUALITY = 70, // "!=" + LESS_EQUAL = 71, // "<=" + GREATER_EQUAL = 72, // ">=" + LESS = 73, // "<" + GREATER = 74, // ">" + NOT = 75, // "!" + COMPLEMENT = 76, // "~" + ASSIGN = 77, // "=" + ASSIGN_ADD = 78, // "+=" + ASSIGN_SUB = 79, // "-=" + ASSIGN_MUL = 80, // "*=" + ASSIGN_DIV = 81, // "/=" + ASSIGN_MOD = 82, // "%=" + ASSIGN_BW_OR = 83, // "|=" + ASSIGN_BW_AND = 84, // "&=" + ASSIGN_BW_EXOR = 85, // "^=" + ASSIGN_RSHIFT = 86, // ">>=" + ASSIGN_LSHIFT = 87, // "<<=" + BITWISE_OR = 88, // "|" + BITWISE_AND = 89, // "&" + BITWISE_EXOR = 90, // "^" + ADD = 91, // "+" + SUB = 92, // "-" + MUL = 93, // "*" + DIV = 94, // "/" + MOD = 95, // "%" + PATH = 96, // "path" + IDENTIFIER = 97, // "identifier" + STRING = 98, // "string literal" + ISTRING = 99, // "localized string" + FLOAT = 100, // "float" + INTEGER = 101, // "integer" + SIZEOF = 102, // SIZEOF + ADD_ARRAY = 103, // ADD_ARRAY + THEN = 104, // THEN + TERN = 105, // TERN + NEG = 106, // NEG + ANIMREF = 107, // ANIMREF + PREINC = 108, // PREINC + PREDEC = 109, // PREDEC + POSTINC = 110, // POSTINC + POSTDEC = 111 // POSTDEC + }; + /// Backward compatibility alias (Bison 3.6). + typedef token_kind_type yytokentype; + }; + + /// Token kind, as returned by yylex. + typedef token::token_kind_type 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 = 112, ///< Number of tokens. + S_YYEMPTY = -2, + S_YYEOF = 0, // "end of file" + S_YYerror = 1, // error + S_YYUNDEF = 2, // "invalid token" + S_SH_DEFINE = 3, // "#define" + S_SH_UNDEF = 4, // "#undef" + S_SH_IFDEF = 5, // "#ifdef" + S_SH_IFNDEF = 6, // "#ifndef" + S_SH_IF = 7, // "#if" + S_SH_ELIF = 8, // "#elif" + S_SH_ELSE = 9, // "#else" + S_SH_ENDIF = 10, // "#endif" + S_DEVBEGIN = 11, // "/#" + S_DEVEND = 12, // "#/" + S_INLINE = 13, // "#inline" + S_INCLUDE = 14, // "#include" + S_USINGTREE = 15, // "#using_animtree" + S_ANIMTREE = 16, // "#animtree" + S_ENDON = 17, // "endon" + S_NOTIFY = 18, // "notify" + S_WAIT = 19, // "wait" + S_WAITTILL = 20, // "waittill" + S_WAITTILLMATCH = 21, // "waittillmatch" + S_WAITTILLFRAMEEND = 22, // "waittillframeend" + S_IF = 23, // "if" + S_ELSE = 24, // "else" + S_DO = 25, // "do" + S_WHILE = 26, // "while" + S_FOR = 27, // "for" + S_FOREACH = 28, // "foreach" + S_IN = 29, // "in" + S_SWITCH = 30, // "switch" + S_CASE = 31, // "case" + S_DEFAULT = 32, // "default" + S_BREAK = 33, // "break" + S_CONTINUE = 34, // "continue" + S_RETURN = 35, // "return" + S_BREAKPOINT = 36, // "breakpoint" + S_PROFBEGIN = 37, // "prof_begin" + S_PROFEND = 38, // "prof_end" + S_THREAD = 39, // "thread" + S_CHILDTHREAD = 40, // "childthread" + S_THISTHREAD = 41, // "thisthread" + S_CALL = 42, // "call" + S_TRUE = 43, // "true" + S_FALSE = 44, // "false" + S_UNDEFINED = 45, // "undefined" + S_SIZE = 46, // "size" + S_GAME = 47, // "game" + S_SELF = 48, // "self" + S_ANIM = 49, // "anim" + S_LEVEL = 50, // "level" + S_LPAREN = 51, // "(" + S_RPAREN = 52, // ")" + S_LBRACE = 53, // "{" + S_RBRACE = 54, // "}" + S_LBRACKET = 55, // "[" + S_RBRACKET = 56, // "]" + S_COMMA = 57, // "," + S_DOT = 58, // "." + S_DOUBLECOLON = 59, // "::" + S_COLON = 60, // ":" + S_SEMICOLON = 61, // ";" + S_QMARK = 62, // "?" + S_INCREMENT = 63, // "++" + S_DECREMENT = 64, // "--" + S_LSHIFT = 65, // "<<" + S_RSHIFT = 66, // ">>" + S_OR = 67, // "||" + S_AND = 68, // "&&" + S_EQUALITY = 69, // "==" + S_INEQUALITY = 70, // "!=" + S_LESS_EQUAL = 71, // "<=" + S_GREATER_EQUAL = 72, // ">=" + S_LESS = 73, // "<" + S_GREATER = 74, // ">" + S_NOT = 75, // "!" + S_COMPLEMENT = 76, // "~" + S_ASSIGN = 77, // "=" + S_ASSIGN_ADD = 78, // "+=" + S_ASSIGN_SUB = 79, // "-=" + S_ASSIGN_MUL = 80, // "*=" + S_ASSIGN_DIV = 81, // "/=" + S_ASSIGN_MOD = 82, // "%=" + S_ASSIGN_BW_OR = 83, // "|=" + S_ASSIGN_BW_AND = 84, // "&=" + S_ASSIGN_BW_EXOR = 85, // "^=" + S_ASSIGN_RSHIFT = 86, // ">>=" + S_ASSIGN_LSHIFT = 87, // "<<=" + S_BITWISE_OR = 88, // "|" + S_BITWISE_AND = 89, // "&" + S_BITWISE_EXOR = 90, // "^" + S_ADD = 91, // "+" + S_SUB = 92, // "-" + S_MUL = 93, // "*" + S_DIV = 94, // "/" + S_MOD = 95, // "%" + S_PATH = 96, // "path" + S_IDENTIFIER = 97, // "identifier" + S_STRING = 98, // "string literal" + S_ISTRING = 99, // "localized string" + S_FLOAT = 100, // "float" + S_INTEGER = 101, // "integer" + S_SIZEOF = 102, // SIZEOF + S_ADD_ARRAY = 103, // ADD_ARRAY + S_THEN = 104, // THEN + S_TERN = 105, // TERN + S_NEG = 106, // NEG + S_ANIMREF = 107, // ANIMREF + S_PREINC = 108, // PREINC + S_PREDEC = 109, // PREDEC + S_POSTINC = 110, // POSTINC + S_POSTDEC = 111, // POSTDEC + S_YYACCEPT = 112, // $accept + S_root = 113, // root + S_program = 114, // program + S_inline = 115, // inline + S_include = 116, // include + S_declaration = 117, // declaration + S_decl_usingtree = 118, // decl_usingtree + S_decl_constant = 119, // decl_constant + S_decl_thread = 120, // decl_thread + S_stmt = 121, // stmt + S_stmt_or_dev = 122, // stmt_or_dev + S_stmt_list = 123, // stmt_list + S_stmt_or_dev_list = 124, // stmt_or_dev_list + S_stmt_dev = 125, // stmt_dev + S_stmt_block = 126, // stmt_block + S_stmt_expr = 127, // stmt_expr + S_stmt_call = 128, // stmt_call + S_stmt_assign = 129, // stmt_assign + S_stmt_endon = 130, // stmt_endon + S_stmt_notify = 131, // stmt_notify + S_stmt_wait = 132, // stmt_wait + S_stmt_waittill = 133, // stmt_waittill + S_stmt_waittillmatch = 134, // stmt_waittillmatch + S_stmt_waittillframeend = 135, // stmt_waittillframeend + S_stmt_if = 136, // stmt_if + S_stmt_ifelse = 137, // stmt_ifelse + S_stmt_while = 138, // stmt_while + S_stmt_dowhile = 139, // stmt_dowhile + S_stmt_for = 140, // stmt_for + S_stmt_foreach = 141, // stmt_foreach + S_stmt_switch = 142, // stmt_switch + S_stmt_case = 143, // stmt_case + S_stmt_default = 144, // stmt_default + S_stmt_break = 145, // stmt_break + S_stmt_continue = 146, // stmt_continue + S_stmt_return = 147, // stmt_return + S_stmt_breakpoint = 148, // stmt_breakpoint + S_stmt_prof_begin = 149, // stmt_prof_begin + S_stmt_prof_end = 150, // stmt_prof_end + S_expr = 151, // expr + S_expr_or_empty = 152, // expr_or_empty + S_expr_assign = 153, // expr_assign + S_expr_increment = 154, // expr_increment + S_expr_decrement = 155, // expr_decrement + S_expr_ternary = 156, // expr_ternary + S_expr_binary = 157, // expr_binary + S_expr_primitive = 158, // expr_primitive + S_expr_complement = 159, // expr_complement + S_expr_negate = 160, // expr_negate + S_expr_not = 161, // expr_not + S_expr_call = 162, // expr_call + S_expr_method = 163, // expr_method + S_expr_function = 164, // expr_function + S_expr_pointer = 165, // expr_pointer + S_expr_add_array = 166, // expr_add_array + S_expr_parameters = 167, // expr_parameters + S_expr_arguments = 168, // expr_arguments + S_expr_arguments_no_empty = 169, // expr_arguments_no_empty + S_expr_reference = 170, // expr_reference + S_expr_tuple = 171, // expr_tuple + S_expr_tuple_arguments = 172, // expr_tuple_arguments + S_expr_tuple_types = 173, // expr_tuple_types + S_expr_array = 174, // expr_array + S_expr_field = 175, // expr_field + S_expr_size = 176, // expr_size + S_expr_paren = 177, // expr_paren + S_expr_object = 178, // expr_object + S_expr_thisthread = 179, // expr_thisthread + S_expr_empty_array = 180, // expr_empty_array + S_expr_undefined = 181, // expr_undefined + S_expr_game = 182, // expr_game + S_expr_self = 183, // expr_self + S_expr_anim = 184, // expr_anim + S_expr_level = 185, // expr_level + S_expr_animation = 186, // expr_animation + S_expr_animtree = 187, // expr_animtree + S_expr_identifier_nosize = 188, // expr_identifier_nosize + S_expr_identifier = 189, // expr_identifier + S_expr_path = 190, // expr_path + S_expr_istring = 191, // expr_istring + S_expr_string = 192, // expr_string + S_expr_vector = 193, // expr_vector + S_expr_float = 194, // expr_float + S_expr_integer = 195, // expr_integer + S_expr_false = 196, // expr_false + S_expr_true = 197 // expr_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 () YY_NOEXCEPT + : 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (std::move (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (std::move (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (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, ast::call&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::call& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::decl&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::decl& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::decl_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 ast::decl_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, ast::decl_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 ast::decl_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, ast::decl_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 ast::decl_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, ast::expr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_add_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 ast::expr_add_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::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 ast::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, ast::expr_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 ast::expr_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, ast::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 ast::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, ast::expr_complement::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_complement::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_field::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_field::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_identifier::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_identifier::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_method::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_method::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_negate::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_negate::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_not::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_not::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_paren::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_paren::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_path::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_path::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_reference::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_reference::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_size::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_size::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_tuple::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_tuple::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_vector::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::stmt&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::stmt_breakpoint::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_breakpoint::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::stmt_dev::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_dev::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::stmt_dowhile::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_dowhile::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::stmt_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 ast::stmt_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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::stmt_prof_begin::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_prof_begin::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::stmt_prof_end::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_prof_end::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, 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 + + /// 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.template destroy< ast::call > (); + break; + + case symbol_kind::S_declaration: // declaration + value.template destroy< ast::decl > (); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.template destroy< ast::decl_constant::ptr > (); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.template destroy< ast::decl_thread::ptr > (); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.template destroy< ast::decl_usingtree::ptr > (); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.template destroy< ast::expr > (); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.template destroy< ast::expr_add_array::ptr > (); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.template destroy< ast::expr_anim::ptr > (); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.template destroy< ast::expr_animation::ptr > (); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.template destroy< ast::expr_animtree::ptr > (); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.template destroy< ast::expr_arguments::ptr > (); + break; + + case symbol_kind::S_expr_array: // expr_array + value.template destroy< ast::expr_array::ptr > (); + break; + + case symbol_kind::S_expr_call: // expr_call + value.template destroy< ast::expr_call::ptr > (); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.template destroy< ast::expr_complement::ptr > (); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.template destroy< ast::expr_empty_array::ptr > (); + break; + + case symbol_kind::S_expr_false: // expr_false + value.template destroy< ast::expr_false::ptr > (); + break; + + case symbol_kind::S_expr_field: // expr_field + value.template destroy< ast::expr_field::ptr > (); + break; + + case symbol_kind::S_expr_float: // expr_float + value.template destroy< ast::expr_float::ptr > (); + break; + + case symbol_kind::S_expr_game: // expr_game + value.template destroy< ast::expr_game::ptr > (); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.template destroy< ast::expr_identifier::ptr > (); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.template destroy< ast::expr_integer::ptr > (); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.template destroy< ast::expr_istring::ptr > (); + break; + + case symbol_kind::S_expr_level: // expr_level + value.template destroy< ast::expr_level::ptr > (); + break; + + case symbol_kind::S_expr_method: // expr_method + value.template destroy< ast::expr_method::ptr > (); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.template destroy< ast::expr_negate::ptr > (); + break; + + case symbol_kind::S_expr_not: // expr_not + value.template destroy< ast::expr_not::ptr > (); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.template destroy< ast::expr_parameters::ptr > (); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.template destroy< ast::expr_paren::ptr > (); + break; + + case symbol_kind::S_expr_path: // expr_path + value.template destroy< ast::expr_path::ptr > (); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.template destroy< ast::expr_reference::ptr > (); + break; + + case symbol_kind::S_expr_self: // expr_self + value.template destroy< ast::expr_self::ptr > (); + break; + + case symbol_kind::S_expr_size: // expr_size + value.template destroy< ast::expr_size::ptr > (); + break; + + case symbol_kind::S_expr_string: // expr_string + value.template destroy< ast::expr_string::ptr > (); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.template destroy< ast::expr_thisthread::ptr > (); + break; + + case symbol_kind::S_expr_true: // expr_true + value.template destroy< ast::expr_true::ptr > (); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.template destroy< ast::expr_tuple::ptr > (); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.template destroy< ast::expr_undefined::ptr > (); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.template destroy< ast::expr_vector::ptr > (); + break; + + case symbol_kind::S_include: // include + value.template destroy< ast::include::ptr > (); + break; + + case symbol_kind::S_program: // program + value.template destroy< ast::program::ptr > (); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.template destroy< ast::stmt > (); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.template destroy< ast::stmt_assign::ptr > (); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.template destroy< ast::stmt_break::ptr > (); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.template destroy< ast::stmt_breakpoint::ptr > (); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.template destroy< ast::stmt_call::ptr > (); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.template destroy< ast::stmt_case::ptr > (); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.template destroy< ast::stmt_continue::ptr > (); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.template destroy< ast::stmt_default::ptr > (); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.template destroy< ast::stmt_dev::ptr > (); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.template destroy< ast::stmt_dowhile::ptr > (); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.template destroy< ast::stmt_endon::ptr > (); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.template destroy< ast::stmt_expr::ptr > (); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.template destroy< ast::stmt_for::ptr > (); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.template destroy< ast::stmt_foreach::ptr > (); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.template destroy< ast::stmt_if::ptr > (); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.template destroy< ast::stmt_ifelse::ptr > (); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.template destroy< ast::stmt_list::ptr > (); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.template destroy< ast::stmt_notify::ptr > (); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.template destroy< ast::stmt_prof_begin::ptr > (); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.template destroy< ast::stmt_prof_end::ptr > (); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.template destroy< ast::stmt_return::ptr > (); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.template destroy< ast::stmt_switch::ptr > (); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.template destroy< ast::stmt_wait::ptr > (); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.template destroy< ast::stmt_waittill::ptr > (); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.template destroy< ast::stmt_waittillframeend::ptr > (); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.template destroy< ast::stmt_waittillmatch::ptr > (); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.template destroy< ast::stmt_while::ptr > (); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.template destroy< std::string > (); + 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. + value_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 + { + /// The symbol kind as needed by the constructor. + typedef token_kind_type kind_type; + + /// Default constructor. + by_kind () YY_NOEXCEPT; + +#if 201103L <= YY_CPLUSPLUS + /// Move constructor. + by_kind (by_kind&& that) YY_NOEXCEPT; +#endif + + /// Copy constructor. + by_kind (const by_kind& that) YY_NOEXCEPT; + + /// Constructor from (external) token numbers. + by_kind (kind_type t) YY_NOEXCEPT; + + + + /// 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 () YY_NOEXCEPT {} + + /// Constructor for valueless symbols, and symbols from each type. +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, location_type l) + : super_type (token_kind_type (tok), std::move (l)) +#else + symbol_type (int tok, const location_type& l) + : super_type (token_kind_type (tok), l) +#endif + { +#if !defined _MSC_VER || defined __clang__ + IW6C_ASSERT (tok == token::IW6CEOF + || (token::IW6Cerror <= tok && tok <= token::MOD) + || (token::SIZEOF <= tok && tok <= token::POSTDEC)); +#endif + } +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, std::string v, location_type l) + : super_type (token_kind_type (tok), std::move (v), std::move (l)) +#else + symbol_type (int tok, const std::string& v, const location_type& l) + : super_type (token_kind_type (tok), v, l) +#endif + { +#if !defined _MSC_VER || defined __clang__ + IW6C_ASSERT ((token::PATH <= tok && tok <= token::INTEGER)); +#endif + } + }; + + /// Build a parser object. + parser (xsk::gsc::iw6c::lexer& lexer_yyarg, xsk::gsc::ast::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 IW6CDEBUG + /// 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 token kind. +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IW6CEOF (location_type l) + { + return symbol_type (token::IW6CEOF, std::move (l)); + } +#else + static + symbol_type + make_IW6CEOF (const location_type& l) + { + return symbol_type (token::IW6CEOF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IW6Cerror (location_type l) + { + return symbol_type (token::IW6Cerror, std::move (l)); + } +#else + static + symbol_type + make_IW6Cerror (const location_type& l) + { + return symbol_type (token::IW6Cerror, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IW6CUNDEF (location_type l) + { + return symbol_type (token::IW6CUNDEF, std::move (l)); + } +#else + static + symbol_type + make_IW6CUNDEF (const location_type& l) + { + return symbol_type (token::IW6CUNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_DEFINE (location_type l) + { + return symbol_type (token::SH_DEFINE, std::move (l)); + } +#else + static + symbol_type + make_SH_DEFINE (const location_type& l) + { + return symbol_type (token::SH_DEFINE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_UNDEF (location_type l) + { + return symbol_type (token::SH_UNDEF, std::move (l)); + } +#else + static + symbol_type + make_SH_UNDEF (const location_type& l) + { + return symbol_type (token::SH_UNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_IFDEF (location_type l) + { + return symbol_type (token::SH_IFDEF, std::move (l)); + } +#else + static + symbol_type + make_SH_IFDEF (const location_type& l) + { + return symbol_type (token::SH_IFDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_IFNDEF (location_type l) + { + return symbol_type (token::SH_IFNDEF, std::move (l)); + } +#else + static + symbol_type + make_SH_IFNDEF (const location_type& l) + { + return symbol_type (token::SH_IFNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_IF (location_type l) + { + return symbol_type (token::SH_IF, std::move (l)); + } +#else + static + symbol_type + make_SH_IF (const location_type& l) + { + return symbol_type (token::SH_IF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_ELIF (location_type l) + { + return symbol_type (token::SH_ELIF, std::move (l)); + } +#else + static + symbol_type + make_SH_ELIF (const location_type& l) + { + return symbol_type (token::SH_ELIF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_ELSE (location_type l) + { + return symbol_type (token::SH_ELSE, std::move (l)); + } +#else + static + symbol_type + make_SH_ELSE (const location_type& l) + { + return symbol_type (token::SH_ELSE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_ENDIF (location_type l) + { + return symbol_type (token::SH_ENDIF, std::move (l)); + } +#else + static + symbol_type + make_SH_ENDIF (const location_type& l) + { + return symbol_type (token::SH_ENDIF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEVBEGIN (location_type l) + { + return symbol_type (token::DEVBEGIN, std::move (l)); + } +#else + static + symbol_type + make_DEVBEGIN (const location_type& l) + { + return symbol_type (token::DEVBEGIN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEVEND (location_type l) + { + return symbol_type (token::DEVEND, std::move (l)); + } +#else + static + symbol_type + make_DEVEND (const location_type& l) + { + return symbol_type (token::DEVEND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INLINE (location_type l) + { + return symbol_type (token::INLINE, std::move (l)); + } +#else + static + symbol_type + make_INLINE (const location_type& l) + { + return symbol_type (token::INLINE, 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_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_DO (location_type l) + { + return symbol_type (token::DO, std::move (l)); + } +#else + static + symbol_type + make_DO (const location_type& l) + { + return symbol_type (token::DO, 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_BREAKPOINT (location_type l) + { + return symbol_type (token::BREAKPOINT, std::move (l)); + } +#else + static + symbol_type + make_BREAKPOINT (const location_type& l) + { + return symbol_type (token::BREAKPOINT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PROFBEGIN (location_type l) + { + return symbol_type (token::PROFBEGIN, std::move (l)); + } +#else + static + symbol_type + make_PROFBEGIN (const location_type& l) + { + return symbol_type (token::PROFBEGIN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PROFEND (location_type l) + { + return symbol_type (token::PROFEND, std::move (l)); + } +#else + static + symbol_type + make_PROFEND (const location_type& l) + { + return symbol_type (token::PROFEND, 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_MUL (location_type l) + { + return symbol_type (token::ASSIGN_MUL, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_MUL (const location_type& l) + { + return symbol_type (token::ASSIGN_MUL, 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_BW_OR (location_type l) + { + return symbol_type (token::ASSIGN_BW_OR, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BW_OR (const location_type& l) + { + return symbol_type (token::ASSIGN_BW_OR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_BW_AND (location_type l) + { + return symbol_type (token::ASSIGN_BW_AND, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BW_AND (const location_type& l) + { + return symbol_type (token::ASSIGN_BW_AND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_BW_EXOR (location_type l) + { + return symbol_type (token::ASSIGN_BW_EXOR, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BW_EXOR (const location_type& l) + { + return symbol_type (token::ASSIGN_BW_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_MUL (location_type l) + { + return symbol_type (token::MUL, std::move (l)); + } +#else + static + symbol_type + make_MUL (const location_type& l) + { + return symbol_type (token::MUL, 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_PATH (std::string v, location_type l) + { + return symbol_type (token::PATH, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_PATH (const std::string& v, const location_type& l) + { + return symbol_type (token::PATH, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IDENTIFIER (std::string v, location_type l) + { + return symbol_type (token::IDENTIFIER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IDENTIFIER (const std::string& v, const location_type& l) + { + return symbol_type (token::IDENTIFIER, 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_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_INTEGER (std::string v, location_type l) + { + return symbol_type (token::INTEGER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INTEGER (const std::string& v, const location_type& l) + { + return symbol_type (token::INTEGER, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SIZEOF (location_type l) + { + return symbol_type (token::SIZEOF, std::move (l)); + } +#else + static + symbol_type + make_SIZEOF (const location_type& l) + { + return symbol_type (token::SIZEOF, 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) YY_NOEXCEPT; + + /// 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) YY_NOEXCEPT; + + 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_kind_type enum. + static symbol_kind_type yytranslate_ (int t) YY_NOEXCEPT; + + + + // 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 symbol kind of the accessing symbol of + // state STATE-NUM. + static const unsigned char yystos_[]; + + // YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. + static const unsigned char yyr1_[]; + + // YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. + static const signed char yyr2_[]; + + +#if IW6CDEBUG + // 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) YY_NOEXCEPT + : 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) YY_NOEXCEPT + : 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) YY_NOEXCEPT; + + /// Constants. + enum + { + yylast_ = 2371, ///< Last index in yytable_. + yynnts_ = 86, ///< Number of nonterminal symbols. + yyfinal_ = 22 ///< Termination state number. + }; + + + // User arguments. + xsk::gsc::iw6c::lexer& lexer; + xsk::gsc::ast::program::ptr& ast; + + }; + + inline + parser::symbol_kind_type + parser::yytranslate_ (int t) YY_NOEXCEPT + { + 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.copy< ast::call > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.copy< ast::decl > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.copy< ast::decl_constant::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.copy< ast::decl_thread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.copy< ast::decl_usingtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.copy< ast::expr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.copy< ast::expr_add_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.copy< ast::expr_anim::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.copy< ast::expr_animation::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.copy< ast::expr_animtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.copy< ast::expr_arguments::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.copy< ast::expr_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.copy< ast::expr_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.copy< ast::expr_complement::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.copy< ast::expr_empty_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.copy< ast::expr_false::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.copy< ast::expr_field::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.copy< ast::expr_float::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.copy< ast::expr_game::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.copy< ast::expr_identifier::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.copy< ast::expr_integer::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.copy< ast::expr_istring::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.copy< ast::expr_level::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.copy< ast::expr_method::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.copy< ast::expr_negate::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.copy< ast::expr_not::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.copy< ast::expr_parameters::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.copy< ast::expr_paren::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.copy< ast::expr_path::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.copy< ast::expr_reference::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.copy< ast::expr_self::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.copy< ast::expr_size::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.copy< ast::expr_string::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.copy< ast::expr_thisthread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.copy< ast::expr_true::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.copy< ast::expr_tuple::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.copy< ast::expr_undefined::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.copy< ast::expr_vector::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.copy< ast::include::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.copy< ast::program::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.copy< ast::stmt > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.copy< ast::stmt_assign::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.copy< ast::stmt_break::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.copy< ast::stmt_breakpoint::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.copy< ast::stmt_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.copy< ast::stmt_case::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.copy< ast::stmt_continue::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.copy< ast::stmt_default::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.copy< ast::stmt_dev::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.copy< ast::stmt_dowhile::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.copy< ast::stmt_endon::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.copy< ast::stmt_expr::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.copy< ast::stmt_for::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.copy< ast::stmt_foreach::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.copy< ast::stmt_if::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.copy< ast::stmt_ifelse::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.copy< ast::stmt_list::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.copy< ast::stmt_notify::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.copy< ast::stmt_prof_begin::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.copy< ast::stmt_prof_end::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.copy< ast::stmt_return::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.copy< ast::stmt_switch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.copy< ast::stmt_wait::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.copy< ast::stmt_waittill::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.copy< ast::stmt_waittillframeend::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.copy< ast::stmt_waittillmatch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.copy< ast::stmt_while::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.copy< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (YY_MOVE (s.value)); + break; + + default: + break; + } + + location = YY_MOVE (s.location); + } + + // by_kind. + inline + parser::by_kind::by_kind () YY_NOEXCEPT + : kind_ (symbol_kind::S_YYEMPTY) + {} + +#if 201103L <= YY_CPLUSPLUS + inline + parser::by_kind::by_kind (by_kind&& that) YY_NOEXCEPT + : kind_ (that.kind_) + { + that.clear (); + } +#endif + + inline + parser::by_kind::by_kind (const by_kind& that) YY_NOEXCEPT + : kind_ (that.kind_) + {} + + inline + parser::by_kind::by_kind (token_kind_type t) YY_NOEXCEPT + : 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::iw6c +#line 5546 "parser.hpp" + + + + +#endif // !YY_IW6C_PARSER_HPP_INCLUDED diff --git a/src/experimental/iw6c/xsk/resolver.cpp b/src/experimental/iw6c/xsk/resolver.cpp new file mode 100644 index 00000000..dfe2d683 --- /dev/null +++ b/src/experimental/iw6c/xsk/resolver.cpp @@ -0,0 +1,483 @@ +// Copyright 2022 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 "iw6c.hpp" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +#endif + +namespace xsk::gsc::iw6c +{ + +std::unordered_map opcode_map; +std::unordered_map function_map; +std::unordered_map method_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 token_map_rev; +std::unordered_map> files; +read_cb_type read_callback = nullptr; +std::set string_map; + +void resolver::init(read_cb_type callback) +{ + read_callback = callback; +} + +void resolver::cleanup() +{ + files.clear(); +} + +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 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 std::string(itr->second); + } + + throw 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 +{ + if (name.starts_with("_func_")) + { + return static_cast(std::stoul(name.substr(6), nullptr, 16)); + } + + const auto itr = function_map_rev.find(name); + + if (itr != function_map_rev.end()) + { + return itr->second; + } + + throw 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 std::string(itr->second); + } + + return utils::string::va("_func_%04X", id); +} + +auto resolver::method_id(const std::string& name) -> std::uint16_t +{ + if (name.starts_with("_meth_")) + { + return static_cast(std::stoul(name.substr(6), nullptr, 16)); + } + + const auto itr = method_map_rev.find(name); + + if (itr != method_map_rev.end()) + { + return itr->second; + } + + throw 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 std::string(itr->second); + } + + return utils::string::va("_meth_%04X", id); +} + +auto resolver::token_id(const std::string& name) -> std::uint16_t +{ + if (name.starts_with("_id_")) + { + return static_cast(std::stoul(name.substr(4), nullptr, 16)); + } + + const auto itr = token_map_rev.find(name); + + if (itr != token_map_rev.end()) + { + return itr->second; + } + + return 0; +} + +auto resolver::token_name(std::uint16_t id) -> std::string +{ + const auto itr = token_map.find(id); + + if (itr != token_map.end()) + { + return std::string(itr->second); + } + + return utils::string::va("_id_%04X", id); +} + +auto resolver::find_function(const std::string& name) -> bool +{ + if (name.starts_with("_func_")) return true; + + 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 +{ + if (name.starts_with("_meth_")) return true; + + const auto itr = method_map_rev.find(name); + + if (itr != method_map_rev.end()) + { + return true; + } + + return false; +} + +auto resolver::make_token(std::string_view str) -> std::string +{ + if (str.starts_with("_id_") || str.starts_with("_func_") || str.starts_with("_meth_")) + { + return std::string(str); + } + + auto data = std::string(str.begin(), str.end()); + + for (std::size_t i = 0; i < data.size(); i++) + { + data[i] = static_cast(std::tolower(static_cast(str[i]))); + if (data[i] == '\\') data[i] = '/'; + } + + return data; +} + +auto resolver::file_data(const std::string& name) -> std::tuple +{ + const auto itr = files.find(name); + + if (itr != files.end()) + { + return { &itr->first ,reinterpret_cast(itr->second.data()), itr->second.size() }; + } + + auto data = read_callback(name); + + const auto res = files.insert({ name, std::move(data)}); + + if (res.second) + { + return { &res.first->first, reinterpret_cast(res.first->second.data()), res.first->second.size() }; + } + + throw error("couldn't open gsc file '" + name + "'"); +} + +std::set paths +{ + "character"sv, + "codescripts"sv, + "common_scripts"sv, + "destructible_scripts"sv, + "maps"sv, + "vehicle_scripts"sv, + "xmodelalias"sv, + "maps/animated_models"sv, + "maps/createart"sv, + "maps/createfx"sv, + "maps/interactive_models"sv, + "maps/mp"sv, + "maps/mp/agents"sv, + "maps/mp/alien"sv, + "maps/mp/bots"sv, + "maps/mp/gametypes"sv, + "maps/mp/killstreaks"sv, + "maps/mp/perks"sv, + "maps/mp/agents/alien"sv, + "maps/mp/agents/dog"sv, + "maps/mp/agents/alien/alien_ancestor"sv, + "maps/mp/agents/alien/alien_kraken"sv, + "maps/mp/agents/alien/alien_spider"sv, +}; + +auto resolver::fs_to_game_path(const std::filesystem::path& file) -> std::filesystem::path +{ + auto result = std::filesystem::path(); + auto root = false; + + for (auto& entry : file) + { + if (!root && paths.contains(entry.string())) + { + result = entry; + root = true; + } + else if (paths.contains(result.string())) + { + result /= entry; + } + } + + return result.empty() ? file : result; +} + +const std::array, 153> opcode_list +{{ + { 0x1D, "OP_CastFieldObject" }, + { 0x1E, "OP_SetLocalVariableFieldCached" }, + { 0x1F, "OP_plus" }, + { 0x20, "OP_RemoveLocalVariables" }, + { 0x21, "OP_EvalSelfFieldVariableRef" }, + { 0x22, "OP_ScriptFarMethodChildThreadCall" }, + { 0x23, "OP_GetGameRef" }, + { 0x24, "OP_EvalAnimFieldVariable" }, + { 0x25, "OP_EvalLevelFieldVariableRef" }, + { 0x26, "OP_GetThisthread" }, + { 0x27, "OP_greater" }, + { 0x28, "OP_waittillmatch" }, + { 0x29, "OP_shift_right" }, + { 0x2A, "OP_dec" }, + { 0x2B, "OP_JumpOnTrue" }, + { 0x2C, "OP_bit_or" }, + { 0x2D, "OP_equality" }, + { 0x2E, "OP_ClearLocalVariableFieldCached0" }, + { 0x2F, "OP_notify" }, + { 0x30, "OP_GetVector" }, + { 0x31, "OP_ScriptMethodChildThreadCallPointer" }, + { 0x32, "OP_voidCodepos" }, + { 0x33, "OP_GetByte" }, + { 0x34, "OP_ScriptFarMethodThreadCall" }, + { 0x35, "OP_SetSelfFieldVariableField" }, + { 0x36, "OP_JumpOnFalseExpr" }, + { 0x37, "OP_GetUndefined" }, + { 0x38, "OP_jumpback" }, + { 0x39, "OP_JumpOnTrueExpr" }, + { 0x3A, "OP_CallBuiltin0" }, + { 0x3B, "OP_CallBuiltin1" }, + { 0x3C, "OP_CallBuiltin2" }, + { 0x3D, "OP_CallBuiltin3" }, + { 0x3E, "OP_CallBuiltin4" }, + { 0x3F, "OP_CallBuiltin5" }, + { 0x40, "OP_CallBuiltin" }, + { 0x41, "OP_SetLocalVariableFieldCached0" }, + { 0x42, "OP_ClearFieldVariable" }, + { 0x43, "OP_GetLevel" }, + { 0x44, "OP_size" }, + { 0x45, "OP_SafeSetWaittillVariableFieldCached" }, + { 0x46, "OP_ScriptLocalThreadCall" }, + { 0x47, "OP_AddArray" }, + { 0x48, "OP_endon" }, + { 0x49, "OP_EvalFieldVariable" }, + { 0x4A, "OP_shift_left" }, + { 0x4B, "OP_EvalLocalArrayRefCached0" }, + { 0x4C, "OP_Return" }, + { 0x4D, "OP_CreateLocalVariable" }, + { 0x4E, "OP_SafeSetVariableFieldCached0" }, + { 0x4F, "OP_GetBuiltinFunction" }, + { 0x50, "OP_ScriptLocalMethodCall" }, + { 0x51, "OP_CallBuiltinMethodPointer" }, + { 0x52, "OP_ScriptLocalChildThreadCall" }, + { 0x53, "OP_GetSelfObject" }, + { 0x54, "OP_GetGame" }, + { 0x55, "OP_SetLevelFieldVariableField" }, + { 0x56, "OP_EvalArray" }, + { 0x57, "OP_GetSelf" }, + { 0x58, "OP_End" }, + { 0x59, "OP_EvalSelfFieldVariable" }, + { 0x5A, "OP_less_equal" }, + { 0x5B, "OP_EvalLocalVariableCached0" }, + { 0x5C, "OP_EvalLocalVariableCached1" }, + { 0x5D, "OP_EvalLocalVariableCached2" }, + { 0x5E, "OP_EvalLocalVariableCached3" }, + { 0x5F, "OP_EvalLocalVariableCached4" }, + { 0x60, "OP_EvalLocalVariableCached5" }, + { 0x61, "OP_EvalLocalVariableCached" }, + { 0x62, "OP_EvalNewLocalArrayRefCached0" }, + { 0x63, "OP_ScriptMethodChildThreadCallPointer" }, + { 0x64, "OP_EvalLocalVariableObjectCached" }, + { 0x65, "OP_ScriptLocalMethodThreadCall" }, + { 0x66, "OP_GetInteger" }, + { 0x67, "OP_ScriptMethodCallPointer" }, + { 0x68, "OP_checkclearparams" }, + { 0x69, "OP_SetAnimFieldVariableField" }, + { 0x6A, "OP_UNK_1" }, + { 0x6B, "OP_minus" }, + { 0x6C, "OP_ScriptLocalFunctionCall2" }, + { 0x6D, "OP_GetNegUnsignedShort" }, + { 0x6E, "OP_GetNegByte" }, + { 0x6F, "OP_SafeCreateVariableFieldCached" }, + { 0x70, "OP_greater_equal" }, + { 0x71, "OP_vector" }, + { 0x72, "OP_GetBuiltinMethod" }, + { 0x73, "OP_endswitch" }, + { 0x74, "OP_ClearArray" }, + { 0x75, "OP_DecTop" }, + { 0x76, "OP_CastBool" }, + { 0x77, "OP_EvalArrayRef" }, + { 0x78, "OP_SetNewLocalVariableFieldCached0" }, + { 0x79, "OP_GetZero" }, + { 0x7A, "OP_wait" }, + { 0x7B, "OP_waittill" }, + { 0x7C, "OP_GetIString" }, + { 0x7D, "OP_ScriptFarFunctionCall" }, + { 0x7E, "OP_GetAnimObject" }, + { 0x7F, "OP_GetAnimTree" }, + { 0x80, "OP_EvalLocalArrayCached" }, + { 0x81, "OP_mod" }, + { 0x82, "OP_ScriptFarThreadCall" }, + { 0x83, "OP_GetUnsignedShort" }, + { 0x84, "OP_clearparams" }, + { 0x85, "OP_ScriptMethodThreadCallPointer" }, + { 0x86, "OP_ScriptFunctionCallPointer" }, + { 0x87, "OP_EmptyArray" }, + { 0x88, "OP_SafeSetVariableFieldCached" }, + { 0x89, "OP_UNK_2" }, + { 0x8A, "OP_EvalFieldVariableRef" }, + { 0x8B, "OP_ScriptLocalMethodChildThreadCall" }, + { 0x8C, "OP_UNK_3" }, + { 0x8D, "OP_GetFloat" }, + { 0x8E, "OP_EvalLocalVariableRefCached" }, + { 0x8F, "OP_JumpOnFalse" }, + { 0x90, "OP_BoolComplement" }, + { 0x91, "OP_ScriptThreadCallPointer" }, + { 0x92, "OP_ScriptFarFunctionCall2" }, + { 0x93, "OP_less" }, + { 0x94, "OP_BoolNot" }, + { 0x95, "OP_waittillFrameEnd" }, + { 0x96, "OP_GetString" }, + { 0x97, "OP_EvalLevelFieldVariable" }, + { 0x98, "OP_GetLevelObject" }, + { 0x99, "OP_inc" }, + { 0x9A, "OP_CallBuiltinMethod0" }, + { 0x9B, "OP_CallBuiltinMethod1" }, + { 0x9C, "OP_CallBuiltinMethod2" }, + { 0x9D, "OP_CallBuiltinMethod3" }, + { 0x9E, "OP_CallBuiltinMethod4" }, + { 0x9F, "OP_CallBuiltinMethod5" }, + { 0xA0, "OP_CallBuiltinMethod" }, + { 0xA1, "OP_GetAnim" }, + { 0xA2, "OP_switch" }, + { 0xA3, "OP_SetVariableField" }, + { 0xA4, "OP_divide" }, + { 0xA5, "OP_GetLocalFunction" }, + { 0xA6, "OP_ScriptFarChildThreadCall" }, + { 0xA7, "OP_multiply" }, + { 0xA8, "OP_ClearLocalVariableFieldCached" }, + { 0xA9, "OP_EvalAnimFieldVariableRef" }, + { 0xAA, "OP_EvalLocalArrayRefCached" }, + { 0xAB, "OP_EvalLocalVariableRefCached0" }, + { 0xAC, "OP_bit_and" }, + { 0xAD, "OP_GetAnimation" }, + { 0xAE, "OP_GetFarFunction" }, + { 0xAF, "OP_CallBuiltinPointer" }, + { 0xB0, "OP_jump" }, + { 0xB1, "OP_PreScriptCall" }, + { 0xB2, "OP_ScriptFarMethodCall" }, + { 0xB3, "OP_inequality" }, + { 0xB4, "OP_ScriptLocalFunctionCall" }, + { 0xB5, "OP_bit_ex_or" }, +}}; + +const std::array, 0> function_list +{{ +}}; + +const std::array, 0> method_list +{{ +}}; + +const std::array, 0> token_list +{{ +}}; + +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()); + token_map.reserve(token_list.size()); + token_map_rev.reserve(token_list.size()); + + for (const auto& entry : opcode_list) + { + opcode_map.insert({ entry.first, entry.second }); + opcode_map_rev.insert({ entry.second, entry.first }); + } + + for (const auto& entry : function_list) + { + function_map.insert({ entry.first, entry.second }); + function_map_rev.insert({ entry.second, entry.first }); + } + + for (const auto& entry : method_list) + { + method_map.insert({ entry.first, entry.second }); + method_map_rev.insert({ entry.second, entry.first }); + } + + for (const auto& entry : token_list) + { + token_map.insert({ entry.first, entry.second }); + token_map_rev.insert({ entry.second, entry.first }); + } + } +}; + +__init__ _; + +} // namespace xsk::gsc::iw6c + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/src/experimental/iw6c/xsk/resolver.hpp b/src/experimental/iw6c/xsk/resolver.hpp new file mode 100644 index 00000000..aca7c8eb --- /dev/null +++ b/src/experimental/iw6c/xsk/resolver.hpp @@ -0,0 +1,40 @@ +// Copyright 2022 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::iw6c +{ + +class resolver +{ +public: + static void init(read_cb_type callback); + static void cleanup(); + + 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 token_id(const std::string& name) -> std::uint16_t; + static auto token_name(std::uint16_t id) -> std::string; + + static auto find_function(const std::string& name) -> bool; + static auto find_method(const std::string& name) -> bool; + + static void add_function(const std::string& name, std::uint16_t id); + static void add_method(const std::string& name, std::uint16_t id); + + static auto make_token(std::string_view str) -> std::string; + static auto file_data(const std::string& name) -> std::tuple; + static auto fs_to_game_path(const std::filesystem::path& file) -> std::filesystem::path; +}; + +} // namespace xsk::gsc::iw6c diff --git a/src/experimental/s1_console/stdafx.cpp b/src/experimental/s1c/stdafx.cpp similarity index 100% rename from src/experimental/s1_console/stdafx.cpp rename to src/experimental/s1c/stdafx.cpp diff --git a/src/experimental/s1_console/stdafx.hpp b/src/experimental/s1c/stdafx.hpp similarity index 100% rename from src/experimental/s1_console/stdafx.hpp rename to src/experimental/s1c/stdafx.hpp diff --git a/src/experimental/s1c/xsk/assembler.cpp b/src/experimental/s1c/xsk/assembler.cpp new file mode 100644 index 00000000..8418560b --- /dev/null +++ b/src/experimental/s1c/xsk/assembler.cpp @@ -0,0 +1,556 @@ +// Copyright 2022 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 "s1c.hpp" + +namespace xsk::gsc::s1c +{ + +auto assembler::output_script() -> std::vector +{ + std::vector script; + + if (script_ == nullptr) return script; + + script.resize(script_->pos()); + std::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()); + std::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; + 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 opdata = utils::string::parse_code(line); + + if (switchnum) + { + if (opdata[0] == "case" || opdata[0] == "default") + { + for (auto& entry : opdata) + { + func->instructions.back()->data.push_back(entry); + } + switchnum--; + continue; + } + + throw asm_error("invalid instruction inside endswitch \""s + line + "\"!"); + } + else + { + auto inst = std::make_unique(); + inst->index = index; + inst->opcode = resolver::opcode_id(opdata[0]); + inst->size = opcode_size(inst->opcode); + opdata.erase(opdata.begin()); + inst->data = std::move(opdata); + + switch (static_cast(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[0] = inst->data[0].substr(4); + break; + case opcode::OP_endswitch: + switchnum = static_cast(std::stoi(inst->data[0])); + inst->size += 7 * switchnum; + break; + default: + break; + } + + index += inst->size; + func->instructions.push_back(std::move(inst)); + } + } + } + + assemble(file, functions); +} + +void assembler::assemble(const std::string& file, std::vector& funcs) +{ + script_ = std::make_unique(0x100000); + stack_ = std::make_unique(0x100000); + filename_ = file; + functions_ = std::move(funcs); + + script_->write_endian(static_cast(opcode::OP_End)); + + for (const auto& func : functions_) + { + assemble_function(func); + } +} + +void assembler::assemble_function(const function::ptr& func) +{ + labels_ = func->labels; + + func->id = resolver::token_id(func->name); + + stack_->write_endian(func->size); + stack_->write_endian(static_cast(func->id)); + + if (func->id == 0) + { + stack_->write_c_string(func->name); + } + + for (const auto& inst : func->instructions) + { + assemble_instruction(inst); + } +} + +void assembler::assemble_instruction(const instruction::ptr& inst) +{ + script_->write_endian(static_cast(inst->opcode)); + + switch (static_cast(inst->opcode)) + { + case opcode::OP_Return: + case opcode::OP_BoolNot: + case opcode::OP_CastBool: + case opcode::OP_inequality: + case opcode::OP_GetThisthread: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_checkclearparams: + case opcode::OP_CastFieldObject: + case opcode::OP_End: + case opcode::OP_size: + case opcode::OP_EmptyArray: + case opcode::OP_bit_and: + case opcode::OP_less_equal: + case opcode::OP_voidCodepos: + // case opcode::OP_ClearVariableField: + case opcode::OP_divide: + case opcode::OP_GetSelf: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_plus: + case opcode::OP_BoolComplement: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_inc: + case opcode::OP_clearparams: + case opcode::OP_EvalLocalVariableRefCached0: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_endon: + case opcode::OP_greater_equal: + case opcode::OP_GetSelfObject: + case opcode::OP_SetVariableField: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_less: + case opcode::OP_GetGameRef: + case opcode::OP_waittillFrameEnd: + case opcode::OP_waitFrame: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_GetLevel: + case opcode::OP_notify: + case opcode::OP_DecTop: + case opcode::OP_shift_left: + case opcode::OP_greater: + 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_GetZero: + case opcode::OP_wait: + case opcode::OP_minus: + // case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_multiply: + case opcode::OP_mod: + case opcode::OP_GetGame: + case opcode::OP_waittill: + case opcode::OP_dec: + case opcode::OP_PreScriptCall: + case opcode::OP_GetAnim: + case opcode::OP_GetUndefined: + case opcode::OP_GetAnimObject: + case opcode::OP_GetLevelObject: + case opcode::OP_bit_ex_or: + case opcode::OP_equality: + case opcode::OP_ClearArray: + case opcode::OP_EvalArrayRef: + case opcode::OP_EvalArray: + case opcode::OP_vector: + case opcode::OP_bit_or: + case opcode::OP_AddArray: + // case opcode::OP_waittillmatch2: + case opcode::OP_shift_right: + break; + case opcode::OP_GetByte: + case opcode::OP_GetNegByte: + script_->write_endian(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetUnsignedShort: + case opcode::OP_GetNegUnsignedShort: + script_->write_endian(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetInteger: + script_->write_endian(std::stoi(inst->data[0])); + break; + case opcode::OP_GetFloat: + script_->write_endian(std::stof(inst->data[0])); + break; + case opcode::OP_GetVector: + inst->size += script_->align(4); + script_->write_endian(std::stof(inst->data[0])); + script_->write_endian(std::stof(inst->data[1])); + script_->write_endian(std::stof(inst->data[2])); + break; + case opcode::OP_GetString: + case opcode::OP_GetIString: + script_->write_endian(0); + stack_->write_c_string(inst->data[0]); + break; + case opcode::OP_GetAnimation: + script_->write_endian(0); + script_->write_endian(0); + stack_->write_c_string(inst->data[0]); + stack_->write_c_string(inst->data[1]); + break; + case opcode::OP_GetAnimTree: + script_->write_endian(0); + stack_->write_c_string(inst->data[0]); + break; + case opcode::OP_waittillmatch: + script_->write_endian(static_cast(std::stoi(inst->data[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_endian(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: + 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_endian(static_cast(std::stoi(inst->data[0]))); + break; + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalMethodCall: + assemble_local_call(inst, false); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + assemble_local_call(inst, true); + break; + case opcode::OP_GetFarFunction: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarMethodCall: + assemble_far_call(inst, false); + break; + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_ScriptFarMethodChildThreadCall: + assemble_far_call(inst, true); + break; + case opcode::OP_CallBuiltin: + assemble_builtin_call(inst, false, true); + break; + case opcode::OP_CallBuiltinMethod: + 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: + 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: + assemble_builtin_call(inst, true, false); + break; + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + assemble_jump(inst, true, false); + break; + case opcode::OP_jumpback: + assemble_jump(inst, false, true); + break; + case opcode::OP_jump: + assemble_jump(inst, false, false); + break; + case opcode::OP_switch: + assemble_switch(inst); + break; + case opcode::OP_endswitch: + assemble_end_switch(inst); + break; + default: + throw asm_error(utils::string::va("unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index)); + } +} + +void assembler::assemble_builtin_call(const instruction::ptr& inst, bool method, bool args) +{ + if (args) + { + script_->write_endian(static_cast(std::stoi(inst->data[1]))); + } + + const auto id = method ? resolver::method_id(inst->data[0]) : resolver::function_id(inst->data[0]); + + script_->write_endian(id); +} + +void assembler::assemble_local_call(const instruction::ptr& inst, bool thread) +{ + const auto addr = resolve_function(inst->data[0]); + const auto offset = static_cast(addr - inst->index - 1); + + assemble_offset(offset); + + if (thread) + { + script_->write_endian(static_cast(std::stoi(inst->data[1]))); + } +} + +void assembler::assemble_far_call(const instruction::ptr& inst, bool thread) +{ + script_->write_endian(0); + script_->write_endian(0); + + if (thread) + { + script_->write_endian(static_cast(std::stoi(inst->data[2]))); + } + + const auto file_id = resolver::token_id(inst->data[0]); + const auto func_id = resolver::token_id(inst->data[1]); + + stack_->write_endian(file_id); + if (file_id == 0) stack_->write_c_string(inst->data[0]); + stack_->write_endian(func_id); + if (func_id == 0) stack_->write_c_string(inst->data[1]); +} + +void assembler::assemble_switch(const instruction::ptr& inst) +{ + const auto addr = resolve_label(inst->data[0]); + + script_->write_endian(addr - inst->index - 4); +} + +void assembler::assemble_end_switch(const instruction::ptr& inst) +{ + const auto count = std::stoul(inst->data[0]); + + script_->write_endian(static_cast(count)); + + std::uint32_t index = inst->index + 3; + + for (auto i = 0u; i < count; i++) + { + if (inst->data[1 + (3 * i)] == "case") + { + if (utils::string::is_number(inst->data[1 + (3 * i) + 1])) + { + script_->write_endian((std::stoi(inst->data[1 + (3 * i) + 1]) & 0xFFFFFF) + 0x800000); + } + else + { + script_->write_endian(i + 1); + stack_->write_c_string(inst->data[1 + (3 * i) + 1]); + } + + index += 4; + + const auto addr = resolve_label(inst->data[1 + (3 * i) + 2]); + + assemble_offset(addr - index); + + index += 3; + } + else if (inst->data[1 + (3 * i)] == "default") + { + script_->write_endian(0); + stack_->write_c_string("\x01"); + + index += 4; + + const auto addr = resolve_label(inst->data[1 + (3 * i) + 1]); + + assemble_offset(addr - index); + + index += 3; + } + else + { + throw asm_error("invalid switch case '" + inst->data[1 + (3 * i)] + "'!"); + } + } +} + +void assembler::assemble_field_variable(const instruction::ptr& inst) +{ + auto id = resolver::token_id(inst->data[0]); + + if (id == 0) id = 0xFFFF; + + script_->write_endian(id); + + if (id > max_string_id) + { + stack_->write_endian(0); + stack_->write_c_string(inst->data[0]); + } +} + +void assembler::assemble_jump(const instruction::ptr& inst, bool expr, bool back) +{ + const auto addr = resolve_label(inst->data[0]); + + if (expr) + { + script_->write_endian(static_cast(addr - inst->index - 3)); + } + else if (back) + { + script_->write_endian(static_cast((inst->index + 3) - addr)); + } + else + { + script_->write_endian(static_cast(addr - inst->index - 5)); + } +} + +void assembler::assemble_offset(std::int32_t offset) +{ + std::array bytes = {}; + + offset = (offset << 10) >> 8; + + *reinterpret_cast(bytes.data()) = offset; + + script_->write_endian(bytes[2]); + script_->write_endian(bytes[1]); + script_->write_endian(bytes[0]); +} + +auto assembler::resolve_function(const std::string& name) -> std::int32_t +{ + for (const auto& entry : functions_) + { + if (entry->name == name) + { + return entry->index; + } + } + + throw asm_error("couldn't resolve local function address of '" + name + "'!"); +} + +auto assembler::resolve_label(const std::string& name) -> std::int32_t +{ + for (const auto& entry : labels_) + { + if (entry.second == name) + { + return entry.first; + } + } + + throw asm_error("couldn't resolve label address of '" + name + "'!"); +} + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/assembler.hpp b/src/experimental/s1c/xsk/assembler.hpp new file mode 100644 index 00000000..4462ad4c --- /dev/null +++ b/src/experimental/s1c/xsk/assembler.hpp @@ -0,0 +1,40 @@ +// Copyright 2022 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::s1c +{ + +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& funcs); + +private: + void assemble_function(const function::ptr& func); + void assemble_instruction(const instruction::ptr& inst); + void assemble_builtin_call(const instruction::ptr& inst, bool method, bool args); + void assemble_local_call(const instruction::ptr& inst, bool thread); + void assemble_far_call(const instruction::ptr& inst, bool thread); + void assemble_switch(const instruction::ptr& inst); + void assemble_end_switch(const instruction::ptr& inst); + void assemble_field_variable(const instruction::ptr& inst); + void assemble_jump(const instruction::ptr& inst, bool expr, bool back); + void assemble_offset(std::int32_t offset); + auto resolve_function(const std::string& name) -> std::int32_t; + auto resolve_label(const std::string& name) -> std::int32_t; +}; + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/compiler.cpp b/src/experimental/s1c/xsk/compiler.cpp new file mode 100644 index 00000000..92672efa --- /dev/null +++ b/src/experimental/s1c/xsk/compiler.cpp @@ -0,0 +1,2975 @@ +// Copyright 2022 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 "s1c.hpp" +#include "parser.hpp" +#include "lexer.hpp" + +namespace xsk::gsc::s1c +{ + +auto compiler::output() -> std::vector +{ + return std::move(assembly_); +} + +void compiler::compile(const std::string& file, std::vector& data) +{ + filename_ = file; + + auto prog = parse_buffer(filename_, reinterpret_cast(data.data()), data.size()); + + compile_program(prog); +} + +void compiler::mode(build mode) +{ + mode_ = mode; +} + +auto compiler::parse_buffer(const std::string& file, const char* data, size_t size) -> ast::program::ptr +{ + ast::program::ptr result(nullptr); + + lexer lexer(mode_, file, data, size); + + parser parser(lexer, result); + + if (parser.parse() || result == nullptr) + { + throw comp_error(location(&file), "an unknown error ocurred while parsing gsc file"); + } + + return result; +} + +auto compiler::parse_file(const std::string& file) -> ast::program::ptr +{ + auto data = resolver::file_data(file); + + return parse_buffer(file, std::get<1>(data), std::get<2>(data)); +} + +void compiler::compile_program(const ast::program::ptr& program) +{ + assembly_.clear(); + includes_.clear(); + animtrees_.clear(); + constants_.clear(); + local_functions_.clear(); + index_ = 1; + developer_thread_ = false; + + for (const auto& entry : program->declarations) + { + if (entry == ast::kind::decl_thread) + { + local_functions_.push_back(entry.as_thread->name->value); + } + } + + for (const auto& include : program->includes) + { + emit_include(include); + } + + for (const auto& declaration : program->declarations) + { + emit_declaration(declaration); + } +} + +void compiler::emit_include(const ast::include::ptr& include) +{ + const auto& path = include->path->value; + + for (const auto& inc : includes_) + { + if (inc.name == path) + { + throw comp_error(include->loc(), "duplicated include file '" + path + "'"); + } + } + + if (map_known_includes(path)) return; + + try + { + auto program = parse_file(path); + + std::vector funcs; + + for (const auto& decl : program->declarations) + { + if (decl == ast::kind::decl_thread) + { + funcs.push_back(decl.as_thread->name->value); + } + } + + if (funcs.size() == 0) + { + throw comp_error(include->loc(), "empty include file '" + path + "'"); + } + + includes_.push_back(include_t(path, funcs)); + } + catch(const std::exception& e) + { + throw comp_error(include->loc(), "error parsing include file '" + path + "': " + e.what()); + } +} + +void compiler::emit_declaration(const ast::decl& decl) +{ + switch (decl.kind()) + { + case ast::kind::decl_dev_begin: + developer_thread_ = true; + break; + case ast::kind::decl_dev_end: + developer_thread_ = false; + break; + case ast::kind::decl_usingtree: + emit_decl_usingtree(decl.as_usingtree); + break; + case ast::kind::decl_constant: + emit_decl_constant(decl.as_constant); + break; + case ast::kind::decl_thread: + emit_decl_thread(decl.as_thread); + break; + default: + throw comp_error(decl.loc(), "unknown declaration"); + } +} + +void compiler::emit_decl_usingtree(const ast::decl_usingtree::ptr& animtree) +{ + if (developer_thread_) + throw comp_error(animtree->loc(), "cannot put #using_animtree inside developer block comment"); + + animtrees_.push_back({ animtree->name->value, false }); +} + +void compiler::emit_decl_constant(const ast::decl_constant::ptr& constant) +{ + const auto itr = constants_.find(constant->name->value); + + if (itr != constants_.end()) + throw comp_error(constant->loc(), "duplicated constant '" + constant->name->value + "'"); + + constants_.insert({ constant->name->value, std::move(constant->value) }); +} + +void compiler::emit_decl_thread(const ast::decl_thread::ptr& thread) +{ + function_ = std::make_unique(); + function_->index = index_; + function_->name = thread->name->value; + + auto blk = std::make_unique(); + stack_idx_ = 0; + label_idx_ = 0; + can_break_ = false; + can_continue_ = false; + local_stack_.clear(); + break_blks_.clear(); + continue_blks_.clear(); + + process_thread(thread, blk); + + emit_expr_parameters(thread->params, blk); + emit_stmt_list(thread->stmt, blk, true); + emit_opcode(opcode::OP_End); + + function_->size = index_ - function_->index; + assembly_.push_back(std::move(function_)); +} + +void compiler::emit_stmt(const ast::stmt& stmt, const block::ptr& blk, bool last) +{ + switch (stmt.kind()) + { + case ast::kind::stmt_list: + emit_stmt_list(stmt.as_list, blk, last); + break; + case ast::kind::stmt_dev: + emit_stmt_dev(stmt.as_dev, blk, last); + break; + case ast::kind::stmt_expr: + emit_stmt_expr(stmt.as_expr, blk); + break; + case ast::kind::stmt_call: + emit_stmt_call(stmt.as_call, blk); + break; + case ast::kind::stmt_assign: + emit_stmt_assign(stmt.as_assign, blk); + break; + case ast::kind::stmt_endon: + emit_stmt_endon(stmt.as_endon, blk); + break; + case ast::kind::stmt_notify: + emit_stmt_notify(stmt.as_notify, blk); + break; + case ast::kind::stmt_wait: + emit_stmt_wait(stmt.as_wait, blk); + break; + case ast::kind::stmt_waittill: + emit_stmt_waittill(stmt.as_waittill, blk); + break; + case ast::kind::stmt_waittillmatch: + emit_stmt_waittillmatch(stmt.as_waittillmatch, blk); + break; + case ast::kind::stmt_waittillframeend: + emit_stmt_waittillframeend(stmt.as_waittillframeend, blk); + break; + case ast::kind::stmt_waitframe: + emit_stmt_waitframe(stmt.as_waitframe, blk); + break; + case ast::kind::stmt_if: + emit_stmt_if(stmt.as_if, blk, last); + break; + case ast::kind::stmt_ifelse: + emit_stmt_ifelse(stmt.as_ifelse, blk, last); + break; + case ast::kind::stmt_while: + emit_stmt_while(stmt.as_while, blk); + break; + case ast::kind::stmt_dowhile: + emit_stmt_dowhile(stmt.as_dowhile, blk); + break; + case ast::kind::stmt_for: + emit_stmt_for(stmt.as_for, blk); + break; + case ast::kind::stmt_foreach: + emit_stmt_foreach(stmt.as_foreach, blk); + break; + case ast::kind::stmt_switch: + emit_stmt_switch(stmt.as_switch, blk); + break; + case ast::kind::stmt_case: + emit_stmt_case(stmt.as_case, blk); + break; + case ast::kind::stmt_default: + emit_stmt_default(stmt.as_default, blk); + break; + case ast::kind::stmt_break: + emit_stmt_break(stmt.as_break, blk); + break; + case ast::kind::stmt_continue: + emit_stmt_continue(stmt.as_continue, blk); + break; + case ast::kind::stmt_return: + emit_stmt_return(stmt.as_return, blk); + break; + case ast::kind::stmt_breakpoint: + emit_stmt_breakpoint(stmt.as_breakpoint, blk); + break; + case ast::kind::stmt_prof_begin: + emit_stmt_prof_begin(stmt.as_prof_begin, blk); + break; + case ast::kind::stmt_prof_end: + emit_stmt_prof_end(stmt.as_prof_end, blk); + break; + default: + throw comp_error(stmt.loc(), "unknown statement"); + } +} + +void compiler::emit_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk, bool last) +{ + for (const auto& entry : stmt->list) + { + bool last_ = (&entry == &stmt->list.back() && last) ? true : false; + emit_stmt(entry, blk, last_); + } +} + +void compiler::emit_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk, bool last) +{ + emit_stmt_list(stmt->list, blk, last); +} + +void compiler::emit_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + emit_expr_increment(stmt->expr.as_increment, blk, true); + break; + case ast::kind::expr_decrement: + emit_expr_decrement(stmt->expr.as_decrement, blk, true); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + emit_expr_assign(stmt->expr.as_assign, blk); + break; + case ast::kind::null: + break; + default: + throw comp_error(stmt->loc(), "unknown expr statement expression"); + } +} + +void compiler::emit_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk) +{ + if (stmt->expr == ast::kind::expr_call) + emit_expr_call(stmt->expr.as_call, blk, true); + else if (stmt->expr == ast::kind::expr_method) + emit_expr_method(stmt->expr.as_method, blk, true); + else + throw comp_error(stmt->loc(), "unknown call statement expression"); +} + +void compiler::emit_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + emit_expr_increment(stmt->expr.as_increment, blk, true); + break; + case ast::kind::expr_decrement: + emit_expr_decrement(stmt->expr.as_decrement, blk, true); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + emit_expr_assign(stmt->expr.as_assign, blk); + break; + default: + throw comp_error(stmt->loc(), "unknown assign statement expression"); + } +} + +void compiler::emit_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk) +{ + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_endon); +} + +void compiler::emit_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk) +{ + emit_opcode(opcode::OP_voidCodepos); + + std::reverse(stmt->args->list.begin(), stmt->args->list.end()); + + for (const auto& arg : stmt->args->list) + { + emit_expr(arg, blk); + } + + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_notify); +} + +void compiler::emit_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk) +{ + emit_expr(stmt->time, blk); + emit_opcode(opcode::OP_wait); +} + +void compiler::emit_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk) +{ + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_waittill); + + for (const auto& entry : stmt->args->list) + { + variable_create(entry.as_identifier, blk); + emit_opcode(opcode::OP_SafeSetWaittillVariableFieldCached, variable_access_index(entry.as_identifier, blk)); + } + + emit_opcode(opcode::OP_clearparams); +} + +void compiler::emit_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk) +{ + emit_expr_arguments(stmt->args, blk); + emit_expr(stmt->event, blk); + emit_expr(stmt->obj, blk); + emit_opcode(opcode::OP_waittillmatch, utils::string::va("%d", stmt->args->list.size())); +// emit_opcode(opcode::OP_waittillmatch2); +// TODO!! + emit_opcode(opcode::OP_clearparams); +} + +void compiler::emit_stmt_waittillframeend(const ast::stmt_waittillframeend::ptr&, const block::ptr&) +{ + emit_opcode(opcode::OP_waittillFrameEnd); +} + +void compiler::emit_stmt_waitframe(const ast::stmt_waitframe::ptr&, const block::ptr&) +{ + emit_opcode(opcode::OP_waitFrame); +} + +void compiler::emit_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk, bool last) +{ + auto end_loc = create_label(); + + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, end_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, end_loc); + } + + blk->transfer(stmt->blk); + + emit_stmt(stmt->stmt, stmt->blk, last); + + last ? emit_opcode(opcode::OP_End) : emit_remove_local_vars(stmt->blk); + + insert_label(end_loc); +} + +void compiler::emit_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk, bool last) +{ + std::vector childs; + auto else_loc = create_label(); + auto end_loc = create_label(); + + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, else_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, else_loc); + } + + blk->transfer(stmt->blk_if); + + emit_stmt(stmt->stmt_if, stmt->blk_if, last); + + emit_remove_local_vars(stmt->blk_if); + + if (stmt->blk_if->abort == abort_t::abort_none) + childs.push_back(stmt->blk_if.get()); + + last ? emit_opcode(opcode::OP_End) : emit_opcode(opcode::OP_jump, end_loc); + + insert_label(else_loc); + + blk->transfer(stmt->blk_else); + + emit_stmt(stmt->stmt_else, stmt->blk_else, last); + + last ? emit_opcode(opcode::OP_End) : emit_remove_local_vars(stmt->blk_else); + + if (stmt->blk_else->abort == abort_t::abort_none) + childs.push_back(stmt->blk_else.get()); + + insert_label(end_loc); + + blk->init_from_child(childs); +} + +void compiler::emit_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = true; + can_continue_ = true; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + blk->transfer(stmt->blk); + stmt->blk->loc_break = break_loc; + stmt->blk->loc_continue = continue_loc; + + emit_create_local_vars(stmt->blk); + + blk->local_vars_create_count = stmt->blk->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + auto begin_loc = insert_label(); + + bool const_cond = is_constant_condition(stmt->test); + + if (!const_cond) + { + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, break_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + } + } + + emit_stmt(stmt->stmt, stmt->blk, false); + + insert_label(continue_loc); + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if (const_cond) + blk->init_from_child(break_blks_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = true; + can_continue_ = true; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + blk->transfer(stmt->blk); + stmt->blk->loc_break = break_loc; + stmt->blk->loc_continue = continue_loc; + + emit_create_local_vars(stmt->blk); + + blk->local_vars_create_count = stmt->blk->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + auto begin_loc = insert_label(); + + emit_stmt(stmt->stmt, stmt->blk, false); + + insert_label(continue_loc); + + bool const_cond = is_constant_condition(stmt->test); + + if (!const_cond) + { + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, break_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + } + } + + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if (const_cond) + blk->init_from_child(break_blks_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = false; + can_continue_ = false; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + emit_stmt(stmt->init, blk, false); + + blk->transfer(stmt->blk); + stmt->blk->loc_break = break_loc; + stmt->blk->loc_continue = continue_loc; + + emit_create_local_vars(stmt->blk); + + blk->local_vars_create_count = stmt->blk->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + blk->transfer(stmt->blk_iter); + + auto begin_loc = insert_label(); + + bool const_cond = is_constant_condition(stmt->test); + + if (!const_cond) + { + if (stmt->test == ast::kind::expr_not) + { + emit_expr(stmt->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, break_loc); + } + else + { + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + } + } + + can_break_ = true; + can_continue_ = true; + + emit_stmt(stmt->stmt, stmt->blk, false); + + if (stmt->blk->abort == abort_t::abort_none) + continue_blks_.push_back(stmt->blk.get()); + + can_break_ = false; + can_continue_ = false; + + insert_label(continue_loc); + + stmt->blk_iter->init_from_child(continue_blks_); + + emit_stmt(stmt->iter, stmt->blk_iter, false); + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + + if (const_cond) + blk->init_from_child(break_blks_); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + auto old_break = can_break_; + auto old_continue = can_continue_; + break_blks_.clear(); + continue_blks_.clear(); + can_break_ = false; + can_continue_ = false; + + auto break_loc = create_label(); + auto continue_loc = create_label(); + + emit_expr(stmt->array_expr, blk); + emit_expr_variable_ref(stmt->array, blk, true); + emit_expr_variable(stmt->array, blk); + emit_opcode(opcode::OP_CallBuiltin1, "getfirstarraykey"); + emit_expr_variable_ref(stmt->key_expr, blk, true); + + blk->transfer(stmt->ctx); + stmt->ctx->loc_break = break_loc; + stmt->ctx->loc_continue = continue_loc; + + emit_create_local_vars(stmt->ctx); + + blk->local_vars_create_count = stmt->ctx->local_vars_create_count; + + for (auto i = 0u; i < blk->local_vars_create_count; i++) + { + if (!blk->local_vars.at(i).init) + blk->local_vars.at(i).init = true; + } + + blk->transfer(stmt->ctx_post); + + auto begin_loc = insert_label(); + + emit_expr_variable(stmt->key_expr, blk); + emit_opcode(opcode::OP_CallBuiltin1, "isdefined"); + emit_opcode(opcode::OP_JumpOnFalse, break_loc); + + can_break_ = true; + can_continue_ = true; + + emit_expr_variable(stmt->key_expr, stmt->ctx); + emit_opcode(opcode::OP_EvalLocalArrayCached, variable_access_index(stmt->array.as_identifier, stmt->ctx)); + emit_expr_variable_ref(stmt->value_expr, stmt->ctx, true); + emit_stmt(stmt->stmt, stmt->ctx, false); + + if (stmt->ctx->abort == abort_t::abort_none) + continue_blks_.push_back(stmt->ctx.get()); + + can_break_ = false; + can_continue_ = false; + + insert_label(continue_loc); + + stmt->ctx_post->init_from_child(continue_blks_); + + emit_expr_variable(stmt->key_expr, stmt->ctx_post); + emit_expr_variable(stmt->array, stmt->ctx_post); + emit_opcode(opcode::OP_CallBuiltin2, "getnextarraykey"); + emit_expr_variable_ref(stmt->key_expr, stmt->ctx_post, true); + emit_opcode(opcode::OP_jumpback, begin_loc); + + insert_label(break_loc); + emit_expr_clear_local(stmt->array.as_identifier, blk); + if (!stmt->use_key) emit_expr_clear_local(stmt->key_expr.as_identifier, blk); + + can_break_ = old_break; + can_continue_ = old_continue; + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk) +{ + auto old_breaks = break_blks_; + auto old_break = can_break_; + break_blks_.clear(); + can_break_ = false; + + auto jmptable_loc = create_label(); + auto break_loc = create_label(); + + emit_expr(stmt->test, blk); + emit_opcode(opcode::OP_switch, jmptable_loc); + + can_break_ = true; + + std::vector data; + data.push_back(utils::string::va("%d", stmt->stmt->list.size())); + + bool has_default = false; + block* default_ctx = nullptr; + + for (auto i = 0u; i < stmt->stmt->list.size(); i++) + { + auto& entry = stmt->stmt->list[i]; + + if (entry == ast::kind::stmt_case) + { + if (has_default) + { + comp_error(stmt->loc(), "default must be last case"); + } + + auto& case_ = entry.as_case; + if (case_->label == ast::kind::expr_integer) + { + auto loc = insert_label(); + data.push_back("case"); + data.push_back(case_->label.as_integer->value); + data.push_back(loc); + } + else if (case_->label == ast::kind::expr_string) + { + auto loc = insert_label(); + data.push_back("case"); + data.push_back(case_->label.as_string->value); + data.push_back(loc); + } + else + { + throw comp_error(stmt->loc(), "case type must be int or string"); + } + + blk->transfer(case_->blk); + case_->blk->loc_break = break_loc; + emit_stmt_list(case_->stmt, case_->blk, false); + if (case_->stmt->list.size() > 0) + emit_remove_local_vars(case_->blk); + } + else if (entry == ast::kind::stmt_default) + { + auto loc = insert_label(); + data.push_back("default"); + data.push_back(loc); + + has_default = true; + default_ctx = entry.as_default->blk.get(); + + blk->transfer(entry.as_default->blk); + entry.as_default->blk->loc_break = break_loc; + emit_stmt_list(entry.as_default->stmt, entry.as_default->blk, false); + if (entry.as_default->stmt->list.size() > 0) + emit_remove_local_vars(entry.as_default->blk); + } + else + { + throw comp_error(entry.loc(), "missing case statement"); + } + } + + if (has_default) + { + if (default_ctx->abort == abort_t::abort_none) + { + break_blks_.push_back(default_ctx); + } + blk->init_from_child(break_blks_); + } + + insert_label(jmptable_loc); + + emit_opcode(opcode::OP_endswitch, data); + + auto offset = static_cast(7 * stmt->stmt->list.size()); + function_->instructions.back()->size += offset; + index_ += offset; + + insert_label(break_loc); + + can_break_ = old_break; + break_blks_ = old_breaks; +} + +void compiler::emit_stmt_case(const ast::stmt_case::ptr& stmt, const block::ptr&) +{ + throw comp_error(stmt->loc(), "illegal case statement"); +} + +void compiler::emit_stmt_default(const ast::stmt_default::ptr& stmt, const block::ptr&) +{ + throw comp_error(stmt->loc(), "illegal default statement"); +} + +void compiler::emit_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk) +{ + if (!can_break_ || blk->abort != abort_t::abort_none || blk->loc_break == "") + throw comp_error(stmt->loc(), "illegal break statement"); + + break_blks_.push_back(blk.get()); + emit_remove_local_vars(blk); + blk->abort = abort_t::abort_break; + emit_opcode(opcode::OP_jump, blk->loc_break); +} + +void compiler::emit_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk) +{ + if (!can_continue_ || blk->abort != abort_t::abort_none || blk->loc_continue == "") + throw comp_error(stmt->loc(), "illegal continue statement"); + + continue_blks_.push_back(blk.get()); + emit_remove_local_vars(blk); + blk->abort = abort_t::abort_continue; + emit_opcode(opcode::OP_jump, blk->loc_continue); +} + +void compiler::emit_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + blk->abort = abort_t::abort_return; + + if (stmt->expr != ast::kind::null) + { + emit_expr(stmt->expr, blk); + emit_opcode(opcode::OP_Return); + } + else + emit_opcode(opcode::OP_End); +} + +void compiler::emit_stmt_breakpoint(const ast::stmt_breakpoint::ptr&, const block::ptr&) +{ + // TODO: +} + +void compiler::emit_stmt_prof_begin(const ast::stmt_prof_begin::ptr&, const block::ptr&) +{ + // TODO: +} + +void compiler::emit_stmt_prof_end(const ast::stmt_prof_end::ptr&, const block::ptr&) +{ + // TODO: +} + +void compiler::emit_expr(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_paren: + emit_expr(expr.as_paren->child, blk); + break; + case ast::kind::expr_ternary: + emit_expr_ternary(expr.as_ternary, blk); + break; + case ast::kind::expr_and: + emit_expr_and(expr.as_and, blk); + break; + case ast::kind::expr_or: + emit_expr_or(expr.as_or, blk); + break; + case ast::kind::expr_equality: + case ast::kind::expr_inequality: + case ast::kind::expr_less: + case ast::kind::expr_greater: + case ast::kind::expr_less_equal: + case ast::kind::expr_greater_equal: + case ast::kind::expr_bitwise_or: + case ast::kind::expr_bitwise_and: + case ast::kind::expr_bitwise_exor: + case ast::kind::expr_shift_left: + case ast::kind::expr_shift_right: + case ast::kind::expr_add: + case ast::kind::expr_sub: + case ast::kind::expr_mul: + case ast::kind::expr_div: + case ast::kind::expr_mod: + emit_expr_binary(expr.as_binary, blk); + break; + case ast::kind::expr_complement: + emit_expr_complement(expr.as_complement, blk); + break; + case ast::kind::expr_negate: + emit_expr_negate(expr.as_negate, blk); + break; + case ast::kind::expr_not: + emit_expr_not(expr.as_not, blk); + break; + case ast::kind::expr_call: + emit_expr_call(expr.as_call, blk, false); + break; + case ast::kind::expr_method: + emit_expr_method(expr.as_method, blk, false); + break; + case ast::kind::expr_reference: + emit_expr_reference(expr.as_reference, blk); + break; + case ast::kind::expr_add_array: + emit_expr_add_array(expr.as_add_array, blk); + break; + case ast::kind::expr_array: + emit_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + emit_expr_field(expr.as_field, blk); + break; + case ast::kind::expr_size: + emit_expr_size(expr.as_size, blk); + break; + case ast::kind::expr_thisthread: + emit_opcode(opcode::OP_GetThisthread); + break; + case ast::kind::expr_empty_array: + emit_opcode(opcode::OP_EmptyArray); + break; + case ast::kind::expr_undefined: + emit_opcode(opcode::OP_GetUndefined); + break; + case ast::kind::expr_game: + emit_opcode(opcode::OP_GetGame); + break; + case ast::kind::expr_self: + emit_opcode(opcode::OP_GetSelf); + break; + case ast::kind::expr_anim: + emit_opcode(opcode::OP_GetAnim); + break; + case ast::kind::expr_level: + emit_opcode(opcode::OP_GetLevel); + break; + case ast::kind::expr_animation: + emit_expr_animation(expr.as_animation); + break; + case ast::kind::expr_animtree: + emit_expr_animtree(expr.as_animtree); + break; + case ast::kind::expr_identifier: + emit_expr_local(expr.as_identifier, blk); + break; + case ast::kind::expr_istring: + emit_expr_istring(expr.as_istring); + break; + case ast::kind::expr_string: + emit_expr_string(expr.as_string); + break; + case ast::kind::expr_vector: + emit_expr_vector(expr.as_vector, blk); + break; + case ast::kind::expr_float: + emit_expr_float(expr.as_float); + break; + case ast::kind::expr_integer: + emit_expr_integer(expr.as_integer); + break; + case ast::kind::expr_false: + emit_expr_false(expr.as_false); + break; + case ast::kind::expr_true: + emit_expr_true(expr.as_true); + break; + case ast::kind::null: + break; + default: + throw comp_error(expr.loc(), "unknown expression"); + } +} + +void compiler::emit_expr_assign(const ast::expr_assign::ptr& expr, const block::ptr& blk) +{ + if (expr->kind() == ast::kind::expr_assign_equal) + { + if (expr->rvalue == ast::kind::expr_undefined) + { + emit_expr_clear(expr->lvalue, blk); + } + else if (expr->lvalue == ast::kind::expr_tuple) + { + emit_expr(expr->rvalue, blk); + emit_expr_tuple(expr->lvalue.as_tuple, blk); + } + else + { + emit_expr(expr->rvalue, blk); + emit_expr_variable_ref(expr->lvalue, blk, true); + } + + return; + } + + emit_expr(expr->lvalue, blk); + emit_expr(expr->rvalue, blk); + + switch (expr->kind()) + { + case ast::kind::expr_assign_add: + emit_opcode(opcode::OP_plus); + break; + case ast::kind::expr_assign_sub: + emit_opcode(opcode::OP_minus); + break; + case ast::kind::expr_assign_mul: + emit_opcode(opcode::OP_multiply); + break; + case ast::kind::expr_assign_div: + emit_opcode(opcode::OP_divide); + break; + case ast::kind::expr_assign_mod: + emit_opcode(opcode::OP_mod); + break; + case ast::kind::expr_assign_shift_left: + emit_opcode(opcode::OP_shift_left); + break; + case ast::kind::expr_assign_shift_right: + emit_opcode(opcode::OP_shift_right); + break; + case ast::kind::expr_assign_bitwise_or: + emit_opcode(opcode::OP_bit_or); + break; + case ast::kind::expr_assign_bitwise_and: + emit_opcode(opcode::OP_bit_and); + break; + case ast::kind::expr_assign_bitwise_exor: + emit_opcode(opcode::OP_bit_ex_or); + break; + default: + throw comp_error(expr->loc(), "unknown assign operation"); + } + + emit_expr_variable_ref(expr->lvalue, blk, true); +} + +void compiler::emit_expr_clear(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_array: + emit_expr(expr.as_array->key, blk); + expr.as_array->obj == ast::kind::expr_game ? emit_opcode(opcode::OP_GetGameRef) : emit_expr_variable_ref(expr.as_array->obj, blk, false); + emit_opcode(opcode::OP_ClearArray); + break; + case ast::kind::expr_field: + emit_expr_object(expr.as_field->obj, blk); + emit_opcode(opcode::OP_ClearFieldVariable, expr.as_field->field->value); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_GetUndefined); + emit_expr_local_ref(expr.as_identifier, blk, true); + break; + default: + throw comp_error(expr.loc(), "unknown clear variable lvalue"); + } +} + +void compiler::emit_expr_clear_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk) +{ + auto index = variable_stack_index(expr, blk); + + if (index == 0) + emit_opcode(opcode::OP_ClearLocalVariableFieldCached0); + else + emit_opcode(opcode::OP_ClearLocalVariableFieldCached, variable_access_index(expr, blk)); +} + +void compiler::emit_expr_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (is_stmt) + { + emit_expr_variable_ref(expr->lvalue, blk, false); + emit_opcode(opcode::OP_inc); + emit_opcode(opcode::OP_SetVariableField); + } + else + { + // TODO: + } +} + +void compiler::emit_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (is_stmt) + { + emit_expr_variable_ref(expr->lvalue, blk, false); + emit_opcode(opcode::OP_dec); + emit_opcode(opcode::OP_SetVariableField); + } + else + { + // TODO: + } +} + +void compiler::emit_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk) +{ + auto else_loc = create_label(); + auto end_loc = create_label(); + + if (expr->test == ast::kind::expr_not) + { + emit_expr(expr->test.as_not->rvalue, blk); + emit_opcode(opcode::OP_JumpOnTrue, else_loc); + } + else + { + emit_expr(expr->test, blk); + emit_opcode(opcode::OP_JumpOnFalse, else_loc); + } + + emit_expr(expr->true_expr, blk); + emit_opcode(opcode::OP_jump, end_loc); + + insert_label(else_loc); + emit_expr(expr->false_expr, blk); + insert_label(end_loc); +} + +void compiler::emit_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->lvalue, blk); + emit_expr(expr->rvalue, blk); + + switch (expr->kind()) + { + case ast::kind::expr_equality: + emit_opcode(opcode::OP_equality); + break; + case ast::kind::expr_inequality: + emit_opcode(opcode::OP_inequality); + break; + case ast::kind::expr_less: + emit_opcode(opcode::OP_less); + break; + case ast::kind::expr_greater: + emit_opcode(opcode::OP_greater); + break; + case ast::kind::expr_less_equal: + emit_opcode(opcode::OP_less_equal); + break; + case ast::kind::expr_greater_equal: + emit_opcode(opcode::OP_greater_equal); + break; + case ast::kind::expr_bitwise_or: + emit_opcode(opcode::OP_bit_or); + break; + case ast::kind::expr_bitwise_and: + emit_opcode(opcode::OP_bit_and); + break; + case ast::kind::expr_bitwise_exor: + emit_opcode(opcode::OP_bit_ex_or); + break; + case ast::kind::expr_shift_left: + emit_opcode(opcode::OP_shift_left); + break; + case ast::kind::expr_shift_right: + emit_opcode(opcode::OP_shift_right); + break; + case ast::kind::expr_add: + emit_opcode(opcode::OP_plus); + break; + case ast::kind::expr_sub: + emit_opcode(opcode::OP_minus); + break; + case ast::kind::expr_mul: + emit_opcode(opcode::OP_multiply); + break; + case ast::kind::expr_div: + emit_opcode(opcode::OP_divide); + break; + case ast::kind::expr_mod: + emit_opcode(opcode::OP_mod); + break; + default: + throw comp_error(expr->loc(), "unknown binary expression"); + } +} + +void compiler::emit_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk) +{ + auto label = create_label(); + + emit_expr(expr->lvalue, blk); + emit_opcode(opcode::OP_JumpOnFalseExpr, label); + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_CastBool); + + insert_label(label); +} + +void compiler::emit_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk) +{ + auto label = create_label(); + + emit_expr(expr->lvalue, blk); + emit_opcode(opcode::OP_JumpOnTrueExpr, label); + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_CastBool); + + insert_label(label); +} + +void compiler::emit_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_BoolComplement); +} + +void compiler::emit_expr_negate(const ast::expr_negate::ptr& expr, const block::ptr& blk) +{ + emit_opcode(opcode::OP_GetZero); + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_minus); +} + +void compiler::emit_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->rvalue, blk); + emit_opcode(opcode::OP_BoolNot); +} + +void compiler::emit_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (expr->call == ast::kind::expr_pointer) + emit_expr_call_pointer(expr->call.as_pointer, blk, is_stmt); + else if (expr->call == ast::kind::expr_function) + emit_expr_call_function(expr->call.as_function, blk, is_stmt); + else + throw comp_error(expr->loc(), "unknown function call expression"); +} + +void compiler::emit_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (expr->mode == ast::call::mode::normal) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + emit_expr(expr->func, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptFunctionCallPointer); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptThreadCallPointer, argcount); + break; + case ast::call::mode::childthread: +// emit_opcode(opcode::OP_ScriptChildThreadCallPointer, argcount); +// TODO! + break; + case ast::call::mode::builtin: + emit_opcode(opcode::OP_CallBuiltinPointer, argcount); + break; + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (is_stmt && mode_ == gsc::build::prod) + { + const auto& name = expr->name->value; + if (name == "assert" || name == "assertex" || name == "assertmsg") return; + } + + auto type = resolve_function_type(expr); + + if (type != ast::call::type::builtin && expr->mode == ast::call::mode::normal && expr->args->list.size() > 0) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + if (type == ast::call::type::local) + { + switch (expr->mode) + { + case ast::call::mode::normal: + if (expr->args->list.size() > 0) + emit_opcode(opcode::OP_ScriptLocalFunctionCall, expr->name->value); + else + emit_opcode(opcode::OP_ScriptLocalFunctionCall2, expr->name->value); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptLocalThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptLocalChildThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no local builtins + break; + } + } + else if (type == ast::call::type::far) + { + switch (expr->mode) + { + case ast::call::mode::normal: + if (expr->args->list.size() > 0) + emit_opcode(opcode::OP_ScriptFarFunctionCall, { expr->path->value, expr->name->value }); + else + emit_opcode(opcode::OP_ScriptFarFunctionCall2, { expr->path->value, expr->name->value }); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptFarThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptFarChildThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no far builtins + break; + } + } + else if (type == ast::call::type::builtin) + { + if (expr->mode != ast::call::mode::normal) + throw comp_error(expr->loc(), "builtin calls can't be threaded"); + + switch (expr->args->list.size()) + { + case 0: + emit_opcode(opcode::OP_CallBuiltin0, expr->name->value); + break; + case 1: + emit_opcode(opcode::OP_CallBuiltin1, expr->name->value); + break; + case 2: + emit_opcode(opcode::OP_CallBuiltin2, expr->name->value); + break; + case 3: + emit_opcode(opcode::OP_CallBuiltin3, expr->name->value); + break; + case 4: + emit_opcode(opcode::OP_CallBuiltin4, expr->name->value); + break; + case 5: + emit_opcode(opcode::OP_CallBuiltin5, expr->name->value); + break; + default: + emit_opcode(opcode::OP_CallBuiltin, { expr->name->value, argcount }); + break; + } + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk, bool is_stmt) +{ + if (expr->call == ast::kind::expr_pointer) + emit_expr_method_pointer(expr->call.as_pointer, expr->obj, blk, is_stmt); + else if (expr->call == ast::kind::expr_function) + emit_expr_method_function(expr->call.as_function, expr->obj, blk, is_stmt); + else + throw comp_error(expr->loc(), "unknown method call expression"); +} + +void compiler::emit_expr_method_pointer(const ast::expr_pointer::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt) +{ + if (expr->mode == ast::call::mode::normal) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + emit_expr(obj, blk); + emit_expr(expr->func, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptMethodCallPointer); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptMethodThreadCallPointer, argcount); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptMethodChildThreadCallPointer, argcount); + break; + case ast::call::mode::builtin: + emit_opcode(opcode::OP_CallBuiltinMethodPointer, argcount); + break; + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_method_function(const ast::expr_function::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt) +{ + auto type = resolve_function_type(expr); + + if (type != ast::call::type::builtin && expr->mode == ast::call::mode::normal) + emit_opcode(opcode::OP_PreScriptCall); + + emit_expr_arguments(expr->args, blk); + emit_expr(obj, blk); + + auto argcount = utils::string::va("%d", expr->args->list.size()); + + if (type == ast::call::type::local) + { + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptLocalMethodCall, expr->name->value); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptLocalMethodThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptLocalMethodChildThreadCall, { expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no local builtins + break; + } + } + else if (type == ast::call::type::far) + { + switch (expr->mode) + { + case ast::call::mode::normal: + emit_opcode(opcode::OP_ScriptFarMethodCall, { expr->path->value, expr->name->value }); + break; + case ast::call::mode::thread: + emit_opcode(opcode::OP_ScriptFarMethodThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::childthread: + emit_opcode(opcode::OP_ScriptFarMethodChildThreadCall, { expr->path->value, expr->name->value, argcount }); + break; + case ast::call::mode::builtin: + // no far builtins + break; + } + } + else if (type == ast::call::type::builtin) + { + if (expr->mode != ast::call::mode::normal) + throw comp_error(expr->loc(), "builtin calls can't be threaded"); + + switch (expr->args->list.size()) + { + case 0: + emit_opcode(opcode::OP_CallBuiltinMethod0, expr->name->value); + break; + case 1: + emit_opcode(opcode::OP_CallBuiltinMethod1, expr->name->value); + break; + case 2: + emit_opcode(opcode::OP_CallBuiltinMethod2, expr->name->value); + break; + case 3: + emit_opcode(opcode::OP_CallBuiltinMethod3, expr->name->value); + break; + case 4: + emit_opcode(opcode::OP_CallBuiltinMethod4, expr->name->value); + break; + case 5: + emit_opcode(opcode::OP_CallBuiltinMethod5, expr->name->value); + break; + default: + emit_opcode(opcode::OP_CallBuiltinMethod, { expr->name->value, argcount }); + break; + } + } + + if (is_stmt) + emit_opcode(opcode::OP_DecTop); +} + +void compiler::emit_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk) +{ + emit_opcode(opcode::OP_EmptyArray); + + for (const auto& arg : expr->args->list) + { + emit_expr(arg, blk); + emit_opcode(opcode::OP_AddArray); + } +} + +void compiler::emit_expr_parameters(const ast::expr_parameters::ptr& expr, const block::ptr& blk) +{ + for (const auto& entry : expr->list) + { + variable_initialize(entry, blk); + emit_opcode(opcode::OP_SafeCreateVariableFieldCached, variable_create_index(entry, blk)); + } + + emit_opcode(opcode::OP_checkclearparams); +} + +void compiler::emit_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk) +{ + std::reverse(expr->list.begin(), expr->list.end()); + + for (auto& entry : expr->list) + { + emit_expr(entry, blk); + } +} + +void compiler::emit_expr_reference(const ast::expr_reference::ptr& expr, const block::ptr&) +{ + bool method = false; + auto type = resolve_reference_type(expr, method); + + switch (type) + { + case ast::call::type::local: + emit_opcode(opcode::OP_GetLocalFunction, expr->name->value); + break; + case ast::call::type::far: + emit_opcode(opcode::OP_GetFarFunction, { expr->path->value, expr->name->value }); + break; + case ast::call::type::builtin: + if (method) + emit_opcode(opcode::OP_GetBuiltinMethod, expr->name->value); + else + emit_opcode(opcode::OP_GetBuiltinFunction, expr->name->value); + break; + } +} + +void compiler::emit_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->obj, blk); + emit_opcode(opcode::OP_size); +} + +void compiler::emit_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + emit_expr_variable_ref(expr->temp, blk, true); + + auto index = 0; + + for (const auto& entry : expr->list) + { + if (index == 0) + emit_opcode(opcode::OP_GetZero); + else + emit_opcode(opcode::OP_GetByte, utils::string::va("%d", index)); + + index++; + + emit_opcode(opcode::OP_EvalLocalArrayCached, variable_access_index(expr->temp.as_identifier, blk)); + + emit_expr_variable_ref(entry, blk, true); + } + + emit_expr_clear_local(expr->temp.as_identifier, blk); +} + +void compiler::emit_expr_variable_ref(const ast::expr& expr, const block::ptr& blk, bool set) +{ + switch (expr.kind()) + { + case ast::kind::expr_array: + emit_expr_array_ref(expr.as_array, blk, set); + break; + case ast::kind::expr_field: + emit_expr_field_ref(expr.as_field, blk, set); + break; + case ast::kind::expr_identifier: + emit_expr_local_ref(expr.as_identifier, blk, set); + break; + default: + throw comp_error(expr.loc(), "invalid lvalue"); + } +} + +void compiler::emit_expr_array_ref(const ast::expr_array::ptr& expr, const block::ptr& blk, bool set) +{ + emit_expr(expr->key, blk); + + switch (expr->obj.kind()) + { + case ast::kind::expr_game: + emit_opcode(opcode::OP_GetGameRef); + emit_opcode(opcode::OP_EvalArrayRef); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_array: + case ast::kind::expr_field: + emit_expr_variable_ref(expr->obj, blk, false); + emit_opcode(opcode::OP_EvalArrayRef); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_identifier: + { + if (!variable_initialized(expr->obj.as_identifier, blk)) + { + variable_initialize(expr->obj.as_identifier, blk); + emit_opcode(opcode::OP_EvalNewLocalArrayRefCached0, variable_create_index(expr->obj.as_identifier, blk)); + + if (!set) throw comp_error(expr->loc(), "INTERNAL: VAR CREATED BUT NOT SET!"); + } + else if (variable_stack_index(expr->obj.as_identifier, blk) == 0) + { + emit_opcode(opcode::OP_EvalLocalArrayRefCached0); + } + else + { + emit_opcode(opcode::OP_EvalLocalArrayRefCached, variable_access_index(expr->obj.as_identifier, blk)); + } + + if (set) emit_opcode(opcode::OP_SetVariableField); + } + break; + case ast::kind::expr_call: + case ast::kind::expr_method: + default: + throw comp_error(expr->loc(), "invalid array lvalue"); + } +} + +void compiler::emit_expr_field_ref(const ast::expr_field::ptr& expr, const block::ptr& blk, bool set) +{ + const auto& field = expr->field->value; + + switch (expr->obj.kind()) + { + case ast::kind::expr_level: + set ? emit_opcode(opcode::OP_SetLevelFieldVariableField, field) : emit_opcode(opcode::OP_EvalLevelFieldVariableRef, field); + break; + case ast::kind::expr_anim: + set ? emit_opcode(opcode::OP_SetAnimFieldVariableField, field) : emit_opcode(opcode::OP_EvalAnimFieldVariableRef, field); + break; + case ast::kind::expr_self: + set ? emit_opcode(opcode::OP_SetSelfFieldVariableField, field) : emit_opcode(opcode::OP_EvalSelfFieldVariableRef, field); + break; + case ast::kind::expr_array: + emit_expr_array(expr->obj.as_array, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_field: + emit_expr_field(expr->obj.as_field, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_EvalLocalVariableObjectCached, variable_access_index(expr->obj.as_identifier, blk)); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_call: + emit_expr_call(expr->obj.as_call, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + case ast::kind::expr_method: + emit_expr_method(expr->obj.as_method, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariableRef, field); + if (set) emit_opcode(opcode::OP_SetVariableField); + break; + default: + throw comp_error(expr->obj.loc(), "not an object"); + } +} + +void compiler::emit_expr_local_ref(const ast::expr_identifier::ptr& expr, const block::ptr& blk, bool set) +{ + const auto itr = constants_.find(expr->value); + + if (itr != constants_.end()) + { + throw comp_error(expr->loc(), "variable name already defined as constant '" + expr->value + "'"); + } + + if (set) + { + if (!variable_initialized(expr, blk)) + { + variable_initialize(expr, blk); + emit_opcode(opcode::OP_SetNewLocalVariableFieldCached0, variable_create_index(expr, blk)); + } + else if (variable_stack_index(expr, blk) == 0) + { + emit_opcode(opcode::OP_SetLocalVariableFieldCached0); + } + else + { + emit_opcode(opcode::OP_SetLocalVariableFieldCached, variable_access_index(expr, blk)); + } + } + else + { + auto index = variable_stack_index(expr, blk); + + if (index == 0) + emit_opcode(opcode::OP_EvalLocalVariableRefCached0); + else + emit_opcode(opcode::OP_EvalLocalVariableRefCached, variable_access_index(expr, blk)); + } +} + +void compiler::emit_expr_variable(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_array: + emit_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + emit_expr_field(expr.as_field, blk); + break; + case ast::kind::expr_identifier: + emit_expr_local(expr.as_identifier, blk); + break; + default: + throw comp_error(expr.loc(), "invalid variable type."); + } +} + +void compiler::emit_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) +{ + emit_expr(expr->key, blk); + + if (expr->obj == ast::kind::expr_identifier) + { + emit_opcode(opcode::OP_EvalLocalArrayCached, variable_access_index(expr->obj.as_identifier, blk)); + } + else + { + emit_expr(expr->obj, blk); + emit_opcode(opcode::OP_EvalArray); + } +} + +void compiler::emit_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) +{ + const auto& field = expr->field->value; + + switch (expr->obj.kind()) + { + case ast::kind::expr_level: + emit_opcode(opcode::OP_EvalLevelFieldVariable, field); + break; + case ast::kind::expr_anim: + emit_opcode(opcode::OP_EvalAnimFieldVariable, field); + break; + case ast::kind::expr_self: + emit_opcode(opcode::OP_EvalSelfFieldVariable, field); + break; + case ast::kind::expr_array: + emit_expr_array(expr->obj.as_array, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_field: + emit_expr_field(expr->obj.as_field, blk); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_call: + emit_expr_call(expr->obj.as_call, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_method: + emit_expr_method(expr->obj.as_method, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_EvalLocalVariableObjectCached, variable_access_index(expr->obj.as_identifier, blk)); + emit_opcode(opcode::OP_EvalFieldVariable, field); + break; + default: + throw comp_error(expr->loc(), "unknown field variable object type"); + } +} + +void compiler::emit_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk) +{ + // is constant ( should only allow: string, loc string, number, vector) + const auto itr = constants_.find(expr->value); + + if (itr != constants_.end()) + { + emit_expr(itr->second, blk); + return; + } + + // is local var + auto index = variable_stack_index(expr, blk); + + switch (index) + { + case 0: + emit_opcode(opcode::OP_EvalLocalVariableCached0); + break; + case 1: + emit_opcode(opcode::OP_EvalLocalVariableCached1); + break; + case 2: + emit_opcode(opcode::OP_EvalLocalVariableCached2); + break; + case 3: + emit_opcode(opcode::OP_EvalLocalVariableCached3); + break; + case 4: + emit_opcode(opcode::OP_EvalLocalVariableCached4); + break; + case 5: + emit_opcode(opcode::OP_EvalLocalVariableCached5); + break; + default: + emit_opcode(opcode::OP_EvalLocalVariableCached, variable_access_index(expr, blk)); + break; + } +} + +void compiler::emit_expr_object(const ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_level: + emit_opcode(opcode::OP_GetLevelObject); + break; + case ast::kind::expr_anim: + emit_opcode(opcode::OP_GetAnimObject); + break; + case ast::kind::expr_self: + emit_opcode(opcode::OP_GetSelfObject); + break; + case ast::kind::expr_array: + emit_expr_array(expr.as_array, blk); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_field: + emit_expr_field(expr.as_field, blk); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_call: + emit_expr_call(expr.as_call, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_method: + emit_expr_method(expr.as_method, blk, false); + emit_opcode(opcode::OP_CastFieldObject); + break; + case ast::kind::expr_identifier: + emit_opcode(opcode::OP_EvalLocalVariableObjectCached, variable_access_index(expr.as_identifier, blk)); + break; + default: + throw comp_error(expr.loc(), "not an object"); + } +} + +void compiler::emit_expr_vector(const ast::expr_vector::ptr& expr, const block::ptr& blk) +{ + std::vector data; + + bool isexpr = false; + + if (expr->x == ast::kind::expr_integer) + data.push_back(expr->x.as_integer->value); + else if (expr->x == ast::kind::expr_float) + data.push_back(expr->x.as_float->value); + else isexpr = true; + + if (expr->y == ast::kind::expr_integer) + data.push_back(expr->y.as_integer->value); + else if (expr->y == ast::kind::expr_float) + data.push_back(expr->y.as_float->value); + else isexpr = true; + + if (expr->z == ast::kind::expr_integer) + data.push_back(expr->z.as_integer->value); + else if (expr->z == ast::kind::expr_float) + data.push_back(expr->z.as_float->value); + else isexpr = true; + + if (!isexpr) + { + auto base = index_ + 1; + auto algn = (base + (4 - 1)) & ~(4 - 1); + emit_opcode(opcode::OP_GetVector, data); + index_ += (algn - base); + } + else + { + emit_expr(expr->z, blk); + emit_expr(expr->y, blk); + emit_expr(expr->x, blk); + emit_opcode(opcode::OP_vector); + } +} + +void compiler::emit_expr_animation(const ast::expr_animation::ptr& expr) +{ + if (animtrees_.size() == 0) + { + throw comp_error(expr->loc(), "trying to use animation without specified using animtree"); + } + + auto& tree = animtrees_.back(); + + if (tree.loaded) + { + emit_opcode(opcode::OP_GetAnimation, { "''", expr->value }); + } + else + { + emit_opcode(opcode::OP_GetAnimation, { tree.name, expr->value }); + tree.loaded = true; + } +} + +void compiler::emit_expr_animtree(const ast::expr_animtree::ptr& expr) +{ + if (animtrees_.size() == 0) + { + throw comp_error(expr->loc(), "trying to use animtree without specified using animtree"); + } + + auto& tree = animtrees_.back(); + + if (tree.loaded) + { + emit_opcode(opcode::OP_GetAnimTree, "''"); + } + else + { + emit_opcode(opcode::OP_GetAnimTree, tree.name); + tree.loaded = true; + } +} + +void compiler::emit_expr_istring(const ast::expr_istring::ptr& expr) +{ + emit_opcode(opcode::OP_GetIString, expr->value); +} + +void compiler::emit_expr_string(const ast::expr_string::ptr& expr) +{ + emit_opcode(opcode::OP_GetString, expr->value); +} + +void compiler::emit_expr_float(const ast::expr_float::ptr& expr) +{ + emit_opcode(opcode::OP_GetFloat, expr->value); +} + +void compiler::emit_expr_integer(const ast::expr_integer::ptr& expr) +{ + auto value = std::atoi(expr->value.data()); + + if (value == 0) + { + emit_opcode(opcode::OP_GetZero); + } + else if (value > 0 && value < 256) + { + emit_opcode(opcode::OP_GetByte, expr->value); + } + else if (value < 0 && value > -256) + { + emit_opcode(opcode::OP_GetNegByte, expr->value.substr(1)); + } + else if (value > 0 && value < 65536) + { + emit_opcode(opcode::OP_GetUnsignedShort, expr->value); + } + else if (value < 0 && value > -65536) + { + emit_opcode(opcode::OP_GetNegUnsignedShort, expr->value.substr(1)); + } + else + { + emit_opcode(opcode::OP_GetInteger, expr->value); + } +} + +void compiler::emit_expr_false(const ast::expr_false::ptr&) +{ + emit_opcode(opcode::OP_GetZero); +} + +void compiler::emit_expr_true(const ast::expr_true::ptr&) +{ + emit_opcode(opcode::OP_GetByte, "1"); +} + +void compiler::emit_create_local_vars(const block::ptr& blk) +{ + if (blk->local_vars_create_count != blk->local_vars_public_count) + { + for (auto i = blk->local_vars_create_count; i < blk->local_vars_public_count; i++) + { + auto data = utils::string::va("%d", blk->local_vars.at(i).create); + emit_opcode(opcode::OP_CreateLocalVariable, data); + blk->local_vars.at(i).init = true; + } + blk->local_vars_create_count = blk->local_vars_public_count; + } +} + +void compiler::emit_remove_local_vars(const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + auto count = blk->local_vars_create_count - blk->local_vars_public_count; + + if (count > 0) + { + auto data = utils::string::va("%d", count); + emit_opcode(opcode::OP_RemoveLocalVariables, data); + } + } +} + +void compiler::emit_opcode(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(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(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 ast::decl_thread::ptr& decl, const block::ptr& blk) +{ + process_expr_parameters(decl->params, blk); + process_stmt_list(decl->stmt, blk); +} + +void compiler::process_stmt(const ast::stmt& stmt, const block::ptr& blk) +{ + switch (stmt.kind()) + { + case ast::kind::stmt_list: + process_stmt_list(stmt.as_list, blk); + break; + case ast::kind::stmt_dev: + process_stmt_dev(stmt.as_dev, blk); + break; + case ast::kind::stmt_expr: + process_stmt_expr(stmt.as_expr, blk); + break; + case ast::kind::stmt_assign: + process_stmt_assign(stmt.as_assign, blk); + break; + case ast::kind::stmt_waittill: + process_stmt_waittill(stmt.as_waittill, blk); + break; + case ast::kind::stmt_if: + process_stmt_if(stmt.as_if, blk); + break; + case ast::kind::stmt_ifelse: + process_stmt_ifelse(stmt.as_ifelse, blk); + break; + case ast::kind::stmt_while: + process_stmt_while(stmt.as_while, blk); + break; + case ast::kind::stmt_dowhile: + process_stmt_dowhile(stmt.as_dowhile, blk); + break; + case ast::kind::stmt_for: + process_stmt_for(stmt.as_for, blk); + break; + case ast::kind::stmt_foreach: + process_stmt_foreach(stmt.as_foreach, blk); + break; + case ast::kind::stmt_switch: + process_stmt_switch(stmt.as_switch, blk); + break; + case ast::kind::stmt_break: + process_stmt_break(stmt.as_break, blk); + break; + case ast::kind::stmt_continue: + process_stmt_continue(stmt.as_continue, blk); + break; + case ast::kind::stmt_return: + process_stmt_return(stmt.as_return, blk); + break; + case ast::kind::stmt_call: + case ast::kind::stmt_endon: + case ast::kind::stmt_notify: + case ast::kind::stmt_wait: + case ast::kind::stmt_waittillmatch: + case ast::kind::stmt_waittillframeend: + case ast::kind::stmt_waitframe: + case ast::kind::stmt_case: + case ast::kind::stmt_default: + case ast::kind::stmt_breakpoint: + case ast::kind::stmt_prof_begin: + case ast::kind::stmt_prof_end: + break; + default: + throw comp_error(stmt.loc(), "unknown statement"); + } +} + +void compiler::process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk) +{ + for (const auto& entry : stmt->list) + { + process_stmt(entry, blk); + } +} + +void compiler::process_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk) +{ + process_stmt_list(stmt->list, blk); +} + +void compiler::process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr(stmt->expr.as_increment->lvalue, blk); + break; + case ast::kind::expr_decrement: + process_expr(stmt->expr.as_decrement->lvalue, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr(stmt->expr.as_assign->lvalue, blk); + break; + case ast::kind::null: + break; + default: + throw comp_error(stmt->loc(), "unknown expr statement expression"); + } +} + +void compiler::process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr(stmt->expr.as_increment->lvalue, blk); + break; + case ast::kind::expr_decrement: + process_expr(stmt->expr.as_decrement->lvalue, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr(stmt->expr.as_assign->lvalue, blk); + break; + default: + throw comp_error(stmt->loc(), "unknown assign statement expression"); + } +} + +void compiler::process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk) +{ + for (const auto& entry : stmt->args->list) + { + if (entry != ast::kind::expr_identifier) + { + throw comp_error(entry.loc(), "illegal waittill param, must be a local variable"); + } + + variable_register(entry.as_identifier->value, blk); + } +} + +void compiler::process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk) +{ + stmt->blk = std::make_unique(); + + blk->copy(stmt->blk); + process_stmt(stmt->stmt, stmt->blk); + + std::vector childs({ stmt->blk.get() }); + blk->merge(childs); +} + +void compiler::process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk) +{ + std::vector childs; + auto abort = abort_t::abort_return; + + stmt->blk_if = std::make_unique(); + stmt->blk_else = std::make_unique(); + + blk->copy(stmt->blk_if); + process_stmt(stmt->stmt_if, stmt->blk_if); + + if (stmt->blk_if->abort <= abort_t::abort_return) + { + abort = stmt->blk_if->abort; + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_if.get()); + } + + blk->copy(stmt->blk_else); + process_stmt(stmt->stmt_else, stmt->blk_else); + + if (stmt->blk_else->abort <= abort) + { + abort = stmt->blk_else->abort; + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_else.get()); + } + + if (blk->abort == abort_t::abort_none) + blk->abort = abort; + + blk->append(childs); + blk->merge(childs); +} + +void compiler::process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk) +{ + bool const_cond = is_constant_condition(stmt->test); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + stmt->blk = std::make_unique(); + + blk->copy(stmt->blk); + process_stmt(stmt->stmt, stmt->blk); + + continue_blks_.push_back(stmt->blk.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + if (const_cond) blk->append(break_blks_); + + blk->merge({ stmt->blk.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk) +{ + bool const_cond = is_constant_condition(stmt->test); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + stmt->blk = std::make_unique(); + + blk->copy(stmt->blk); + process_stmt(stmt->stmt, stmt->blk); + + continue_blks_.push_back(stmt->blk.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + if (const_cond) blk->append(break_blks_); + + blk->merge({ stmt->blk.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk) +{ + bool const_cond = is_constant_condition(stmt->test); + + stmt->blk = std::make_unique(); + stmt->blk_iter = std::make_unique(); + + process_stmt(stmt->init, blk); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + blk->copy(stmt->blk); + blk->copy(stmt->blk_iter); + + process_stmt(stmt->stmt, stmt->blk); + + continue_blks_.push_back(stmt->blk.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + process_stmt(stmt->iter, stmt->blk_iter); + + blk->append({ stmt->blk_iter.get() }); + blk->merge({ stmt->blk_iter.get() }); + + if (const_cond) blk->append(break_blks_); + + blk->merge({ stmt->blk.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk) +{ + auto array_name = utils::string::va("_temp_%d", ++label_idx_); + auto key_name = utils::string::va("_temp_%d", ++label_idx_); + + stmt->array = ast::expr(std::make_unique(stmt->loc(), array_name)); + + if (!stmt->use_key) + stmt->key_expr = ast::expr(std::make_unique(stmt->loc(), key_name)); + + key_name = stmt->key_expr.as_identifier->value; + + // calculate variables + + stmt->ctx = std::make_unique(); + stmt->ctx_post = std::make_unique(); + + // calculate pre_expr variables + process_expr(stmt->array, blk); + + auto old_breaks = break_blks_; + auto old_continues = continue_blks_; + break_blks_.clear(); + continue_blks_.clear(); + + blk->copy(stmt->ctx); + blk->copy(stmt->ctx_post); + + // calculate stmt variables & add missing array access as first stmt + process_expr(stmt->value_expr, stmt->ctx); + process_stmt(stmt->stmt, stmt->ctx); + + continue_blks_.push_back(stmt->ctx.get()); + + for (auto i = 0u; i < continue_blks_.size(); i++) + blk->append({ continue_blks_.at(i) }); + + process_expr(stmt->key_expr, stmt->ctx_post); + + blk->append({ stmt->ctx_post.get() }); + blk->merge({ stmt->ctx_post.get() }); + blk->merge({ stmt->ctx.get() }); + + break_blks_ = old_breaks; + continue_blks_ = old_continues; +} + +void compiler::process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk) +{ + auto stmt_list = std::make_unique(stmt->stmt->loc()); + auto current_case = ast::stmt(nullptr); + + auto num = stmt->stmt->list.size(); + + for (auto i = 0u; i < num; i++) + { + auto& entry = stmt->stmt->list[0]; + + if (entry == ast::kind::stmt_case || entry == ast::kind::stmt_default) + { + if (current_case.as_node != nullptr) + { + stmt_list->list.push_back(std::move(current_case)); + } + + current_case = std::move(stmt->stmt->list[0]); + stmt->stmt->list.erase(stmt->stmt->list.begin()); + } + else + { + if (current_case.as_node != nullptr) + { + if (current_case == ast::kind::stmt_case) + { + current_case.as_case->stmt->list.push_back(std::move(entry)); + stmt->stmt->list.erase(stmt->stmt->list.begin()); + } + else + { + current_case.as_default->stmt->list.push_back(std::move(entry)); + stmt->stmt->list.erase(stmt->stmt->list.begin()); + } + } + else + { + throw comp_error(entry.loc(), "missing case statement"); + } + } + } + + if (current_case.as_node != nullptr) + { + stmt_list->list.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; + block* default_ctx = nullptr; + auto old_breaks = break_blks_; + break_blks_.clear(); + + for (auto i = 0u; i < stmt_list->list.size(); i++) + { + auto& entry = stmt_list->list[i]; + + if (entry == ast::kind::stmt_case) + { + entry.as_case->blk = std::make_unique(); + blk->copy(entry.as_case->blk); + process_stmt_list(entry.as_case->stmt, entry.as_case->blk); + + if (entry.as_case->blk->abort != abort_t::abort_none) + { + if (entry.as_case->blk->abort == abort_t::abort_break ) + { + entry.as_case->blk->abort = abort_t::abort_none; + abort = abort_t::abort_none; + childs.push_back(entry.as_case->blk.get()); + } + else if (entry.as_case->blk->abort <= abort ) + { + abort = entry.as_case->blk->abort; + } + } + } + else if (entry == ast::kind::stmt_default) + { + entry.as_default->blk = std::make_unique(); + blk->copy(entry.as_default->blk); + process_stmt_list(entry.as_default->stmt, entry.as_default->blk); + has_default = true; + default_ctx = entry.as_default->blk.get(); + + if (entry.as_default->blk->abort != abort_t::abort_none) + { + if (entry.as_default->blk->abort == abort_t::abort_break ) + { + entry.as_default->blk->abort = abort_t::abort_none; + abort = abort_t::abort_none; + childs.push_back(entry.as_default->blk.get()); + } + else if (entry.as_default->blk->abort <= abort ) + { + abort = entry.as_default->blk->abort; + } + } + } + } + + stmt->stmt =std::move(stmt_list); + + if (has_default) + { + if (default_ctx->abort == abort_t::abort_none) + { + break_blks_.push_back(default_ctx); + + if (blk->abort == abort_t::abort_none) + blk->abort = abort; + } + + blk->append(break_blks_); + blk->merge(childs); + } + + break_blks_ = old_breaks; +} + +void compiler::process_stmt_break(const ast::stmt_break::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + break_blks_.push_back(blk.get()); + blk->abort = abort_t::abort_break; + } +} + +void compiler::process_stmt_continue(const ast::stmt_continue::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + continue_blks_.push_back(blk.get()); + blk->abort = abort_t::abort_continue; + } +} + +void compiler::process_stmt_return(const ast::stmt_return::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_return; + } +} + +void compiler::process_expr(const ast::expr& expr, const block::ptr& blk) +{ + if (expr == ast::kind::expr_identifier) + { + variable_register(expr.as_identifier->value, blk); + } + else if (expr == ast::kind::expr_array) + { + process_expr(expr.as_array->obj, blk); + } + else if (expr == ast::kind::expr_tuple) + { + process_expr_tuple(expr.as_tuple, blk); + } +} + +void compiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + auto array = utils::string::va("_temp_%d", ++label_idx_); + expr->temp = ast::expr(std::make_unique(expr->loc(), array)); + + process_expr(expr->temp, blk); + + for (const auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void compiler::process_expr_parameters(const ast::expr_parameters::ptr& decl, const block::ptr& blk) +{ + for (const auto& entry : decl->list) + { + variable_register(entry->value, blk); + } +} + +void compiler::variable_register(const std::string& name, const block::ptr& blk) +{ + auto it = std::find_if (blk->local_vars.begin(), blk->local_vars.end(), + [&](const gsc::local_var& v) { return v.name == name; }); + + if (it == blk->local_vars.end()) + { + auto found = false; + for (std::size_t i = 0; i < local_stack_.size(); i++) + { + if (local_stack_[i] == name) + { + blk->local_vars.push_back({ name, static_cast(i), false }); + found = true; + break; + } + } + + if (!found) + { + blk->local_vars.push_back({ name, stack_idx_, false }); + local_stack_.push_back(name); + stack_idx_++; + } + } +} + +void compiler::variable_initialize(const ast::expr_identifier::ptr& name, const block::ptr& blk) +{ + for (std::uint32_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + if (!blk->local_vars[i].init) + { + for (std::uint32_t j = 0; j < i; j++) + { + if (!blk->local_vars[j].init) + { + emit_opcode(opcode::OP_CreateLocalVariable, utils::string::va("%d", blk->local_vars[j].create)); + blk->local_vars[j].init = true; + } + } + blk->local_vars[i].init = true; + blk->local_vars_create_count = i + 1; + return; + } + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +void compiler::variable_create(const ast::expr_identifier::ptr& name, const block::ptr& blk) +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + auto& var = blk->local_vars.at(i); + if (var.name == name->value) + { + if (!var.init) + { + emit_opcode(opcode::OP_CreateLocalVariable, utils::string::va("%d", var.create)); + var.init = true; + blk->local_vars_create_count++; + } + return; + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_stack_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::uint8_t +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + if (blk->local_vars.at(i).init) + { + return static_cast(blk->local_vars_create_count - 1 - i); + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not initialized."); + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_create_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + return utils::string::va("%d", blk->local_vars[i].create); + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_access_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + if (blk->local_vars.at(i).init) + { + return utils::string::va("%d", blk->local_vars_create_count - 1 - i); + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not initialized."); + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::variable_initialized(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> bool +{ + for (std::size_t i = 0; i < blk->local_vars.size(); i++) + { + if (blk->local_vars[i].name == name->value) + { + return blk->local_vars.at(i).init; + } + } + + throw comp_error(name->loc(), "local variable '" + name->value + "' not found."); +} + +auto compiler::resolve_function_type(const ast::expr_function::ptr& expr) -> ast::call::type +{ + if (expr->path->value != "") + return ast::call::type::far; + + auto& name = expr->name->value; + + if (resolver::find_function(name) || resolver::find_method(name)) + return ast::call::type::builtin; + + for (const auto& entry : local_functions_) + { + if (entry == name) + return ast::call::type::local; + } + + for (const auto& inc : includes_) + { + for (const auto& fun : inc.funcs) + { + if (name == fun) + { + expr->path->value = inc.name; + return ast::call::type::far; + } + } + } + + throw comp_error(expr->loc(), "couldn't determine function type"); +} + +auto compiler::resolve_reference_type(const ast::expr_reference::ptr& expr, bool& method) -> ast::call::type +{ + if (expr->path->value != "") + return ast::call::type::far; + + auto& name = expr->name->value; + + if (resolver::find_function(name)) + { + method = false; + return ast::call::type::builtin; + } + + if (resolver::find_method(name)) + { + method = true; + return ast::call::type::builtin; + } + + for (const auto& entry : local_functions_) + { + if (entry == name) + return ast::call::type::local; + } + + for (const auto& inc : includes_) + { + for (const auto& fun : inc.funcs) + { + if (name == fun) + { + expr->path->value = inc.name; + return ast::call::type::far; + } + } + } + + throw comp_error(expr->loc(), "couldn't determine function reference type"); +} + +auto compiler::is_constant_condition(const ast::expr& expr) -> bool +{ + switch (expr.kind()) + { + case ast::kind::null: + case ast::kind::expr_true: + return true; + case ast::kind::expr_false: + throw comp_error(expr.loc(), "condition can't be always false!"); + case ast::kind::expr_integer: + { + auto num = std::stoi(expr.as_integer->value); + if (num != 0) + return true; + else + throw comp_error(expr.loc(), "condition can't be always false!"); + } + default: + break; + } + + return false; +} + +auto compiler::create_label() -> std::string +{ + label_idx_++; + return utils::string::va("loc_%d", label_idx_); +} + +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 (static_cast(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&) -> bool +{ + return false; +} + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/compiler.hpp b/src/experimental/s1c/xsk/compiler.hpp new file mode 100644 index 00000000..afc82f7f --- /dev/null +++ b/src/experimental/s1c/xsk/compiler.hpp @@ -0,0 +1,160 @@ +// Copyright 2022 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::s1c +{ + +enum class opcode : std::uint8_t; + +class compiler : public gsc::compiler +{ + build mode_; + std::string filename_; + std::vector assembly_; + 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::vector break_blks_; + std::vector continue_blks_; + bool can_break_; + bool can_continue_; + bool developer_thread_; + +public: + auto output() -> std::vector; + void compile(const std::string& file, std::vector& data); + void mode(build mode); + +private: + auto parse_buffer(const std::string& file, const char* data, size_t size) -> ast::program::ptr; + auto parse_file(const std::string& file) -> ast::program::ptr; + void compile_program(const ast::program::ptr& program); + void emit_include(const ast::include::ptr& include); + void emit_declaration(const ast::decl& decl); + void emit_decl_usingtree(const ast::decl_usingtree::ptr& animtree); + void emit_decl_constant(const ast::decl_constant::ptr& constant); + void emit_decl_thread(const ast::decl_thread::ptr& thread); + void emit_stmt(const ast::stmt& stmt, const block::ptr& blk, bool last); + void emit_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk); + void emit_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk); + void emit_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk); + void emit_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk); + void emit_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk); + void emit_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk); + void emit_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk); + void emit_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk); + void emit_stmt_waittillframeend(const ast::stmt_waittillframeend::ptr& stmt, const block::ptr& blk); + void emit_stmt_waitframe(const ast::stmt_waitframe::ptr& stmt, const block::ptr& blk); + void emit_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk, bool last); + void emit_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk); + void emit_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk); + void emit_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk); + void emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk); + void emit_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk); + void emit_stmt_case(const ast::stmt_case::ptr& stmt, const block::ptr& blk); + void emit_stmt_default(const ast::stmt_default::ptr& stmt, const block::ptr& blk); + void emit_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk); + void emit_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk); + void emit_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk); + void emit_stmt_breakpoint(const ast::stmt_breakpoint::ptr& stmt, const block::ptr& blk); + void emit_stmt_prof_begin(const ast::stmt_prof_begin::ptr& stmt, const block::ptr& blk); + void emit_stmt_prof_end(const ast::stmt_prof_end::ptr& stmt, const block::ptr& blk); + void emit_expr(const ast::expr& expr, const block::ptr& blk); + void emit_expr_assign(const ast::expr_assign::ptr& expr, const block::ptr& blk); + void emit_expr_clear(const ast::expr& expr, const block::ptr& blk); + void emit_expr_clear_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void emit_expr_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk); + void emit_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk); + void emit_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk); + void emit_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk); + void emit_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk); + void emit_expr_negate(const ast::expr_negate::ptr& expr, const block::ptr& blk); + void emit_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk); + void emit_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk, bool is_stmt); + void emit_expr_method_pointer(const ast::expr_pointer::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt); + void emit_expr_method_function(const ast::expr_function::ptr& expr, const ast::expr& obj, const block::ptr& blk, bool is_stmt); + void emit_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); + void emit_expr_parameters(const ast::expr_parameters::ptr& expr, const block::ptr& blk); + void emit_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); + void emit_expr_reference(const ast::expr_reference::ptr& expr, const block::ptr& blk); + void emit_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); + void emit_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void emit_expr_variable_ref(const ast::expr& expr, const block::ptr& blk, bool set); + void emit_expr_array_ref(const ast::expr_array::ptr& expr, const block::ptr& blk, bool set); + void emit_expr_field_ref(const ast::expr_field::ptr& expr, const block::ptr& blk, bool set); + void emit_expr_local_ref(const ast::expr_identifier::ptr& expr, const block::ptr& blk, bool set); + void emit_expr_variable(const ast::expr& expr, const block::ptr& blk); + void emit_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void emit_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void emit_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void emit_expr_object(const ast::expr& expr, const block::ptr& blk); + void emit_expr_vector(const ast::expr_vector::ptr& expr, const block::ptr& blk); + void emit_expr_animation(const ast::expr_animation::ptr& expr); + void emit_expr_animtree(const ast::expr_animtree::ptr& expr); + void emit_expr_istring(const ast::expr_istring::ptr& expr); + void emit_expr_string(const ast::expr_string::ptr& expr); + void emit_expr_float(const ast::expr_float::ptr& expr); + void emit_expr_integer(const ast::expr_integer::ptr& expr); + void emit_expr_false(const ast::expr_false::ptr& expr); + void emit_expr_true(const ast::expr_true::ptr& expr); + void emit_create_local_vars(const block::ptr& blk); + void emit_remove_local_vars(const block::ptr& blk); + void emit_opcode(opcode op); + void emit_opcode(opcode op, const std::string& data); + void emit_opcode(opcode op, const std::vector& data); + void process_thread(const ast::decl_thread::ptr& decl, const block::ptr& blk); + void process_stmt(const ast::stmt& stmt, const block::ptr& blk); + void process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk); + void process_stmt_dev(const ast::stmt_dev::ptr& stmt, const block::ptr& blk); + void process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk); + void process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk); + void process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk); + void process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk); + void process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk); + void process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk); + void process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk); + void process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk); + void process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk); + void process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk); + void process_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk); + void process_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk); + void process_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk); + void process_expr(const ast::expr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_parameters(const ast::expr_parameters::ptr& decl, const block::ptr& blk); + void variable_register(const std::string& name, const block::ptr& blk); + void variable_initialize(const ast::expr_identifier::ptr& name, const block::ptr& blk); + void variable_create(const ast::expr_identifier::ptr& name, const block::ptr& blk); + auto variable_stack_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::uint8_t; + auto variable_create_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string; + auto variable_access_index(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> std::string; + auto variable_initialized(const ast::expr_identifier::ptr& name, const block::ptr& blk) -> bool; + auto resolve_function_type(const ast::expr_function::ptr& expr) -> ast::call::type; + auto resolve_reference_type(const ast::expr_reference::ptr& expr, bool& method) -> ast::call::type; + auto is_constant_condition(const ast::expr& 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::s1c diff --git a/src/experimental/s1c/xsk/context.cpp b/src/experimental/s1c/xsk/context.cpp new file mode 100644 index 00000000..4bff57e9 --- /dev/null +++ b/src/experimental/s1c/xsk/context.cpp @@ -0,0 +1,23 @@ +// Copyright 2022 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 "s1c.hpp" + +namespace xsk::gsc::s1c +{ + +void context::init(build mode, read_cb_type callback) +{ + compiler_.mode(mode); + resolver::init(callback); +} + +void context::cleanup() +{ + resolver::cleanup(); +} + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/context.hpp b/src/experimental/s1c/xsk/context.hpp new file mode 100644 index 00000000..38140a5f --- /dev/null +++ b/src/experimental/s1c/xsk/context.hpp @@ -0,0 +1,28 @@ +// Copyright 2022 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::s1c +{ + +class context : public gsc::context +{ + s1c::assembler assembler_; + s1c::disassembler disassembler_; + s1c::compiler compiler_; + s1c::decompiler decompiler_; + +public: + void init(build mode, read_cb_type callback); + void cleanup(); + + auto assembler() -> gsc::assembler& { return assembler_; } + auto disassembler() -> gsc::disassembler& { return disassembler_; } + auto compiler() -> gsc::compiler& { return compiler_; } + auto decompiler() -> gsc::decompiler& { return decompiler_; } +}; + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/decompiler.cpp b/src/experimental/s1c/xsk/decompiler.cpp new file mode 100644 index 00000000..c3310740 --- /dev/null +++ b/src/experimental/s1c/xsk/decompiler.cpp @@ -0,0 +1,3444 @@ +// Copyright 2022 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 "s1c.hpp" + +namespace xsk::gsc::s1c +{ + +auto decompiler::output() -> std::vector +{ + std::vector output; + + auto data = std::make_unique(0x100000); + data->write_string("// S1 GSC SOURCE\n"); + data->write_string("// 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& funcs) +{ + filename_ = file; + program_ = std::make_unique(); + + for (const auto& func : funcs) + { + auto name = std::make_unique(func->name); + auto params = std::make_unique(); + auto block = std::make_unique(); + func_ = std::make_unique(std::move(name), std::move(params), std::move(block)); + + stack_ = std::stack(); + labels_ = func->labels; + expr_labels_.clear(); + tern_labels_.clear(); + blocks_.clear(); + + decompile_function(func); + + process_stack(func_); + + program_->declarations.push_back(ast::decl(std::move(func_))); + } +} + +void decompiler::decompile_function(const function::ptr& func) +{ + in_waittill_ = false; + + for (const auto& inst : func->instructions) + { + decompile_instruction(inst); + } + + if (stack_.size() > 0) + { + throw decomp_error("stack isn't empty at function end"); + } + + const auto& stmt = func_->stmt; + + block blk; + blk.loc_end = utils::string::va("loc_%X", stmt->list.back().as_node->loc().begin.line); + + // remove last return + stmt->list.pop_back(); + + blocks_.push_back(blk); + + decompile_statements(stmt); + + blocks_.pop_back(); +} + +void decompiler::decompile_instruction(const instruction::ptr& inst) +{ + decompile_expressions(inst); + + auto loc = location(&filename_, inst->index); + + switch (static_cast(inst->opcode)) + { + case opcode::OP_End: + { + auto expr = ast::expr(std::make_unique()); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_Return: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + auto stmt = ast::stmt(std::make_unique(expr.loc(), std::move(expr))); + func_->stmt->list.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 = ast::expr(std::make_unique(loc, inst->data[0])); + auto y = ast::expr(std::make_unique(loc, inst->data[1])); + auto z = ast::expr(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 value = utils::string::unquote(inst->data[0]); + + if (value != "") + { + auto tree = std::make_unique(loc, inst->data[0]); + auto decl = std::make_unique(loc, std::move(tree)); + program_->declarations.push_back(ast::decl(std::move(decl))); + } + + auto node = std::make_unique(loc, utils::string::unquote(inst->data[1])); + stack_.push(std::move(node)); + break; + } + case opcode::OP_GetAnimTree: + { + auto value = utils::string::unquote(inst->data[0]); + + if (value != "") + { + auto tree = std::make_unique(loc, inst->data[0]); + auto decl = std::make_unique(loc, std::move(tree)); + program_->declarations.push_back(ast::decl(std::move(decl))); + } + + 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 path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(path), std::move(name)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_GetLocalFunction: + { + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(path), std::move(name)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_GetFarFunction: + { + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + auto node = std::make_unique(loc, std::move(path), std::move(name)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CreateLocalVariable: + { + if (in_waittill_) + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + else + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + } + break; + } + case opcode::OP_RemoveLocalVariables: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(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 = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalArray: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalNewLocalArrayRefCached0: + { + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLocalArrayRefCached0: + { + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, "0")); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLocalArrayRefCached: + { + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::make_unique(loc, inst->data[0])); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalArrayRef: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + auto node = std::make_unique(key.loc(), std::move(obj), std::move(key)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ClearArray: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto key = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = key.loc(); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(key))); + auto rvalue = ast::expr(std::make_unique(loc)); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_AddArray: + { + auto value = ast::expr(std::move(stack_.top())); stack_.pop(); + auto array = std::move(stack_.top()); stack_.pop(); + + if (array->kind() == ast::kind::expr_empty_array) + { + auto args = std::make_unique(loc); + args->list.push_back(std::move(value)); + auto node = std::make_unique(array->loc(), std::move(args)); + stack_.push(std::move(node)); + } + else if (array->kind() == ast::kind::expr_add_array) + { + (*(ast::expr_add_array::ptr*)&array)->args->list.push_back(std::move(value)); + stack_.push(std::move(array)); + } + else + { + throw 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 path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalFunctionCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalMethodCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(obj) ,std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalChildThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalMethodThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptLocalMethodChildThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarFunctionCall2: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarFunctionCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarMethodCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarChildThreadCall: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarMethodThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFarMethodChildThreadCall: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto args = std::make_unique(loc); + auto path = std::make_unique(loc, inst->data[0]); + auto name = std::make_unique(loc, inst->data[1]); + + for (auto i = std::stoul(inst->data[2]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptFunctionCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptMethodCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + + while (var->kind() != ast::kind::asm_prescriptcall) + { + args->list.push_back(std::move(var)); + var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::normal)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = func.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } +/* + case opcode::OP_ScriptChildThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = func.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } +*/ + case opcode::OP_ScriptMethodThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::thread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ScriptMethodChildThreadCallPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::childthread)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = func.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethodPointer: + { + auto args = std::make_unique(loc); + auto func = ast::expr(std::move(stack_.top())); stack_.pop(); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(func), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin0: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin1: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 1u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin2: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 2u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin3: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 3u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin4: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 4u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin5: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 5u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltin: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto func = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(func)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod0: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod1: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 1u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj) ,std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod2: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 2u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod3: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 3u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj) ,std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod4: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 4u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod5: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + + for (auto i = 5u; i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_CallBuiltinMethod: + { + auto args = std::make_unique(loc); + auto path = std::make_unique(loc); + auto name = std::make_unique(loc, inst->data[0]); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + + for (auto i = std::stoul(inst->data[1]); i > 0; i--) + { + auto var = std::move(stack_.top()); stack_.pop(); + loc = var->loc(); + args->list.push_back(std::move(var)); + } + + auto call = ast::call(std::make_unique(loc, std::move(path), std::move(name), std::move(args), ast::call::mode::builtin)); + auto node = std::make_unique(loc, std::move(obj), std::move(call)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_DecTop: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + auto stmt = ast::stmt(std::make_unique(expr.loc(), std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_inc: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), false); + stack_.push(std::move(node)); + break; + } + case opcode::OP_dec: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), false); + stack_.push(std::move(node)); + break; + } + case opcode::OP_bit_or: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_bit_ex_or: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_bit_and: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_equality: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_inequality: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_less: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_greater: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_less_equal: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_greater_equal: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_shift_left: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_shift_right: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_plus: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_minus: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_multiply: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_divide: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_mod: + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_wait: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = expr.loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_waittillFrameEnd: + { + auto stmt = ast::stmt(std::make_unique(loc)); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_waitFrame: + { + auto stmt = ast::stmt(std::make_unique(loc)); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_waittill: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = event.as_node->loc(); + auto args = std::make_unique(loc); + auto node = std::make_unique(loc, std::move(obj) , std::move(event), std::move(args)); + stack_.push(std::move(node)); + in_waittill_ = true; + break; + } + case opcode::OP_waittillmatch: + { + auto args = std::make_unique(loc); + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = event.as_node->loc(); + + for (auto i = std::stoul(inst->data[0]); i > 0; i--) + { + auto node = std::move(stack_.top()); stack_.pop(); + loc = node->loc(); + args->list.push_back(std::move(node)); + } + + auto stmt = ast::stmt(std::make_unique(loc, std::move(obj), std::move(event), std::move(args))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_clearparams: + { + if (in_waittill_) + { + auto args = std::make_unique(loc); + auto node = std::move(stack_.top()); stack_.pop(); + + while (node->kind() != ast::kind::stmt_waittill) + { + args->list.push_back(std::move(node)); + node = std::move(stack_.top()); stack_.pop(); + } + + if (node->kind() == ast::kind::stmt_waittill) + { + std::reverse(args->list.begin(), args->list.end()); + (*(ast::stmt_waittill::ptr*)&node)->args = std::move(args); + in_waittill_ = false; + } + + func_->stmt->list.push_back(ast::stmt(std::move(node))); + } + break; + } + case opcode::OP_notify: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + auto args = std::make_unique(loc); + auto node = std::move(stack_.top()); stack_.pop(); + loc = node->loc(); + + while (node->kind() != ast::kind::asm_voidcodepos) + { + args->list.push_back(std::move(node)); + node = std::move(stack_.top()); stack_.pop(); + loc = node->loc(); + } + + auto stmt = ast::stmt(std::make_unique(loc, std::move(obj), std::move(event), std::move(args))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_endon: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + auto event = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = event.as_node->loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(obj), std::move(event))); + func_->stmt->list.push_back(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 = ast::expr(std::move(stack_.top())); stack_.pop(); + auto y = ast::expr(std::move(stack_.top())); stack_.pop(); + auto z = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = z.as_node->loc(); + auto node = std::make_unique(loc, std::move(x), std::move(y), std::move(z)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_size: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLevelFieldVariable: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalAnimFieldVariable: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalSelfFieldVariable: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalFieldVariable: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalLevelFieldVariableRef: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalAnimFieldVariableRef: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalSelfFieldVariableRef: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_EvalFieldVariableRef: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + auto field = std::make_unique(loc, inst->data[0]); + auto node = std::make_unique(loc, std::move(obj), std::move(field)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_ClearFieldVariable: + { + auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = obj.as_node->loc(); + auto name = std::make_unique(loc, inst->data[0]); + auto field = ast::expr(std::make_unique(loc, std::move(obj), std::move(name))); + auto undef = ast::expr(std::make_unique(loc)); + auto expr = ast::expr(std::make_unique(loc, std::move(field), std::move(undef))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SafeCreateVariableFieldCached: + { + auto expr = std::make_unique(loc, "var_" + inst->data[0]); + func_->params->list.push_back(std::move(expr)); + break; + } + case opcode::OP_SafeSetWaittillVariableFieldCached: + { + if (stack_.top()->kind() != ast::kind::asm_create) + { + auto node = std::make_unique(loc, inst->data[0]); + stack_.push(std::move(node)); + } + break; + } + case opcode::OP_SafeSetVariableFieldCached0: + { + auto expr = std::make_unique(loc, "var_0"); + func_->params->list.push_back(std::move(expr)); + break; + } + case opcode::OP_SafeSetVariableFieldCached: + { + auto expr = std::make_unique(loc, "var_" + inst->data[0]); + func_->params->list.push_back(std::move(expr)); + 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 = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetVariableField: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + + if (lvalue.as_node->kind() == ast::kind::expr_increment) + { + auto stmt = ast::stmt(std::make_unique(loc, std::move(lvalue))); + func_->stmt->list.push_back(std::move(stmt)); + } + else if (lvalue.as_node->kind() == ast::kind::expr_decrement) + { + auto stmt = ast::stmt(std::make_unique(loc, std::move(lvalue))); + func_->stmt->list.push_back(std::move(stmt)); + } + else + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + } + break; + } + case opcode::OP_SetAnimFieldVariableField: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetSelfFieldVariableField: + { + auto obj = ast::expr(std::make_unique(loc)); + auto field = std::make_unique(loc, inst->data[0]); + auto lvalue = ast::expr(std::make_unique(loc, std::move(obj), std::move(field))); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetLocalVariableFieldCached0: + { + auto lvalue = ast::expr(std::make_unique(loc, "0")); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetNewLocalVariableFieldCached0: + { + auto lvalue = ast::expr(std::make_unique(loc, inst->data[0])); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + + if (func_->stmt->list.size() > 0) + { + std::vector vars; + + while (func_->stmt->list.back().as_node->kind() == ast::kind::asm_create) + { + auto& entry = func_->stmt->list.back(); + if (loc.begin.line < entry.as_node->loc().begin.line) + { + vars.push_back(entry.as_asm_create->index); + func_->stmt->list.pop_back(); + continue; + } + break; + } + + std::reverse(vars.begin(), vars.end()); + lvalue.as_asm_create->vars = vars; + } + + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_SetLocalVariableFieldCached: + { + auto lvalue = ast::expr(std::make_unique(loc, inst->data[0])); + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = rvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue), std::move(rvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr))); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_ClearLocalVariableFieldCached: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_ClearLocalVariableFieldCached0: + { + auto stmt = ast::stmt(std::make_unique(loc, "0")); + func_->stmt->list.push_back(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_BoolNot: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_BoolComplement: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue)); + stack_.push(std::move(node)); + break; + } + case opcode::OP_switch: + { + auto expr = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = expr.as_node->loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr), inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_endswitch: + { + auto count = inst->data[0]; + inst->data.erase(inst->data.begin()); + auto data = inst->data; + auto stmt = ast::stmt(std::make_unique(loc, data, count)); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_jump: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + if (stack_.size() != 0) tern_labels_.push_back(inst->data[0]); + break; + } + case opcode::OP_jumpback: + { + auto stmt = ast::stmt(std::make_unique(loc, inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_JumpOnTrue: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto expr = ast::expr(std::make_unique(loc, std::move(lvalue))); + auto stmt = ast::stmt(std::make_unique(loc, std::move(expr), inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_JumpOnFalse: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto stmt = ast::stmt(std::make_unique(loc, std::move(lvalue), inst->data[0])); + func_->stmt->list.push_back(std::move(stmt)); + break; + } + case opcode::OP_JumpOnTrueExpr: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), inst->data[0]); + stack_.push(std::move(node)); + expr_labels_.push_back(inst->data[0]); + break; + } + case opcode::OP_JumpOnFalseExpr: + { + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + loc = lvalue.as_node->loc(); + auto node = std::make_unique(loc, std::move(lvalue), inst->data[0]); + stack_.push(std::move(node)); + expr_labels_.push_back(inst->data[0]); + break; + } +// case opcode::OP_waittillmatch2: + case opcode::OP_checkclearparams: + case opcode::OP_CastFieldObject: + case opcode::OP_CastBool: + break; + // case opcode::OP_ClearVariableField + // case opcode::OP_EvalNewLocalVariableRefCached0 + default: + throw decomp_error("unhandled opcode " + resolver::opcode_name(inst->opcode)); + } +} + +void decompiler::decompile_expressions(const instruction::ptr& inst) +{ + const auto itr = labels_.find(inst->index); + + if (itr == labels_.end()) + return; + + for (const auto& expr : expr_labels_) + { + if (expr == itr->second) + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto jump = std::move(stack_.top()); stack_.pop(); + auto loc = jump->loc(); + + if (jump->kind() == ast::kind::asm_jump_true_expr) + { + auto lvalue = std::move((*(ast::asm_jump_true_expr::ptr*)&jump)->expr); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + } + else if (jump->kind() == ast::kind::asm_jump_false_expr) + { + auto lvalue = std::move((*(ast::asm_jump_false_expr::ptr*)&jump)->expr); + auto node = std::make_unique(loc, std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + } + else + { + throw decomp_error("TRIED TO DECOMPILE INVALID JUMP EXPR!"); + } + } + } + + for (const auto& tern : tern_labels_) + { + if (tern == itr->second) + { + auto rvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + auto lvalue = ast::expr(std::move(stack_.top())); stack_.pop(); + + func_->stmt->list.pop_back(); + auto stmt = std::move(func_->stmt->list.back()); + func_->stmt->list.pop_back(); + + if (stmt == ast::kind::asm_jump_cond) + { + auto loc = stmt.as_cond->loc(); + auto node = std::make_unique(loc, std::move(stmt.as_cond->expr), std::move(lvalue), std::move(rvalue)); + stack_.push(std::move(node)); + } + else + { + throw decomp_error("TRIED TO DECOMPILE INVALID TERNARY EXPR!"); + } + } + } +} + +void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) +{ + decompile_loops(stmt); + decompile_switches(stmt); + decompile_ifelses(stmt); + decompile_aborts(stmt); + decompile_tuples(stmt); +} + +void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) +{ + if (stmt->list.size() == 0) + return; + + for (auto i = static_cast(stmt->list.size() - 1); i >= 0; i--) + { + if (stmt->list.at(i) == ast::kind::asm_jump_back) + { + auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); + auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); + + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + if (i - 1 == static_cast(start)) // condition belongs to empty loop + { + decompile_while(stmt, start, i); + i = static_cast(stmt->list.size()); + continue; + } + else if (static_cast(i) < find_location_index(stmt, stmt->list.at(i - 1).as_cond->value)) + { + decompile_dowhile(stmt, i - 1, i); + i = static_cast(stmt->list.size()); + continue; + } + } + + if (i == static_cast(start)) // empty inf loop + { + decompile_inf(stmt, start, i); + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) // no condition + { + decompile_inf(stmt, start, i); + } + else if (stmt->list.at(start).as_cond->value != break_loc) // condition belong to other stmt + { + decompile_inf(stmt, start, i); + } + else // condition belong to loop + { + decompile_loop(stmt, start, i); + } + + i = static_cast(stmt->list.size()); + } + } +} + +void decompiler::decompile_switches(const ast::stmt_list::ptr& stmt) +{ + for (auto i = 0u; i < stmt->list.size(); i++) + { + if (stmt->list.at(i) == ast::kind::asm_switch) + { + decompile_switch(stmt, i); + } + } +} + +void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) +{ + for (auto i = 0u; i < stmt->list.size(); i++) + { + const auto& entry = stmt->list.at(i); + + if (entry == ast::kind::asm_jump_cond) + { + auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); + auto last_loc = blocks_.back().loc_end; + + if (stmt->list.at(j) == ast::kind::asm_jump) + { + // if block is a loop check break, continue + if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) + { + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } + } + else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) + { + decompile_if(stmt, i, j); + } + else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) + { + if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) + { + // if block, have a empty else inside at end + decompile_if(stmt, i, j); + } + else + { + decompile_ifelse(stmt, i, j); // if block with empty else + } + } + else + { + decompile_ifelse(stmt, i, j); + } + } + else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) + { + if(entry.as_cond->value != blocks_.back().loc_end) + { + auto ref = stmt->list.at(j + 1).loc().label(); + + if (find_location_reference(stmt, i + 1, j, ref)) + { + // after return is referenced inside the block + decompile_if(stmt, i, j); + continue; + } + } + + if (blocks_.back().loc_break != "" || blocks_.back().loc_continue != "") + { + decompile_if(stmt, i, j); // inside a loop cant be last + } + else if (j - i == 1) + { + decompile_if(stmt, i, j); // only one explicit return + } + else if (stmt->list.back().as_node->kind() != ast::kind::stmt_return) + { + decompile_if(stmt, i, j); // block end is not a last return + } + else if (blocks_.back().is_last && stmt->list.back().as_node->kind() != ast::kind::stmt_return) + { + decompile_if(stmt, i, j); // inside a last block but is not and inner last + } + else if (find_location_reference(stmt, j, stmt->list.size(), last_loc)) + { + decompile_if(stmt, i, j); // reference to func end after the if + } + else if (blocks_.size() > 1 && !blocks_.back().is_last) + { + decompile_if(stmt, i, j); // fake last ifelse + } + else + { + decompile_ifelse_end(stmt, i, j); // special case + } + } + else + { + decompile_if(stmt, i, j); + } + } + } +} + +void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) +{ + for (auto i = 0u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_jump) + { + auto loc = block->list.at(i).loc(); + auto jump_loc = block->list.at(i).as_jump->value; + + if (jump_loc == blocks_.back().loc_continue) + { + block->list.erase(block->list.begin() + i); + auto stmt = ast::stmt(std::make_unique(loc)); + block->list.insert(block->list.begin() + i, std::move(stmt)); + } + else if (jump_loc == blocks_.back().loc_break) + { + block->list.erase(block->list.begin() + i); + auto stmt = ast::stmt(std::make_unique(loc)); + block->list.insert(block->list.begin() + i, std::move(stmt)); + } + else + { + std::cout << "WARNING: unresolved jump to '" + jump_loc + "', maybe incomplete for loop\n"; + } + } + } +} + +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + const auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + +void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_end = stmt->list.at(begin).as_cond->value; + blk.loc_break = blocks_.back().loc_break; + blk.loc_continue = blocks_.back().loc_continue; + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + + auto if_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + if_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(if_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block if_blk; + if_blk.loc_end = stmt->list.at(end).loc().label(); + if_blk.loc_break = blocks_.back().loc_break; + if_blk.loc_continue = blocks_.back().loc_continue; + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end--; + + auto if_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + if_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(if_blk); + decompile_statements(if_stmt); + blocks_.pop_back(); + + auto end_loc = stmt->list.at(begin).as_jump->value; + stmt->list.erase(stmt->list.begin() + begin); // remove 'jump' + + auto end_idx = (end_loc == blocks_.back().loc_end) ? stmt->list.size() : find_location_index(stmt, end_loc); + + block else_blk; + else_blk.loc_end = end_loc; + else_blk.loc_break = blocks_.back().loc_break; + else_blk.loc_continue = blocks_.back().loc_continue; + + auto else_stmt = std::make_unique(loc); + + for (auto i = begin; i < end_idx; i++) + { + else_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(else_blk); + decompile_statements(else_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)), ast::stmt(std::move(else_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_ifelse_end(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block if_blk; + if_blk.is_last = true; + + auto if_end = find_location_index(stmt, stmt->list.at(begin).as_cond->value) - 1; + if_blk.loc_end = stmt->list.at(if_end).loc().label(); + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end--; + + auto if_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + if_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + stmt->list.erase(stmt->list.begin() + begin); // remove 'return' + + blocks_.push_back(if_blk); + decompile_statements(if_stmt); + blocks_.pop_back(); + + if (begin == stmt->list.size()) + { + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); + } + else + { + block else_blk; + else_blk.is_last = true; + + end = stmt->list.size() - 1; + else_blk.loc_end = stmt->list.at(end).loc().label(); + + auto else_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + else_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + stmt->list.erase(stmt->list.begin() + begin); // remove 'return' + + blocks_.push_back(else_blk); + decompile_statements(else_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(if_stmt)), ast::stmt(std::move(else_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); + } +} + +void decompiler::decompile_inf(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = last_location_index(stmt, end) ? blocks_.back().loc_end : stmt->list.at(end + 1).loc().label(); + blk.loc_end = stmt->list.at(end).loc().label(); + blk.loc_continue = stmt->list.at(end).loc().label(); + + auto loc = stmt->list.at(begin).loc(); + + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto for_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + for_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(for_stmt); + blocks_.pop_back(); + + auto init = ast::stmt(std::make_unique()); + auto test = ast::expr(std::make_unique()); + auto iter = ast::stmt(std::make_unique()); + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(init), std::move(test), std::move(iter), ast::stmt(std::move(for_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_loop(const ast::stmt_list::ptr& block, std::size_t start, std::size_t end) +{ + const auto& last = block->list.at(end - 1); + + if (last == ast::kind::stmt_assign) + { + if (last.as_assign->expr == ast::kind::expr_assign_equal) + { + auto& call = last.as_assign->expr.as_assign_equal->rvalue; + + if (call == ast::kind::expr_call && call.as_call->call == ast::kind::expr_function) + { + if (utils::string::to_lower(call.as_call->call.as_function->name->value) == "getnextarraykey") + { + auto ref = block->list.at(start).loc().label(); + + if (!find_location_reference(block, 0, start, ref)) + { + decompile_foreach(block, start, end); + return; + } + } + } + } + + if (start > 0) // while at func start + { + auto index = 1; + while (block->list.at(start - index) == ast::kind::asm_create) + { + if (start - index > 0) + index++; + else + break; + } + + if (block->list.at(start - index) == ast::kind::stmt_assign) + { + auto ref = block->list.at(end).loc().label(); + auto ref2 = block->list.at(start - index + 1).loc().label(); + + 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 or localVarCreate, 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 ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(end).loc().label(); + blk.loc_continue = stmt->list.at(end).loc().label(); + + auto loc = stmt->list.at(begin).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end--; + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(end - 1).loc().label(); + blk.loc_continue = stmt->list.at(end - 1).loc().label(); + + // collect local vars + std::vector vars; + while (stmt->list.at(begin - 1) == ast::kind::asm_create) + { + vars.push_back(stmt->list.at(begin - 1).as_asm_create->index); + stmt->list.erase(stmt->list.begin() + begin - 1); + begin--; + end--; + } + + std::reverse(vars.begin(), vars.end()); + + auto loc = stmt->list.at(begin - 1).loc(); + auto test = std::move(stmt->list.at(begin).as_cond->expr); + + auto init = ast::stmt(std::make_unique()); + init.as_list->list.push_back(std::move(stmt->list.at(begin - 1))); + init.as_list->is_expr = true; + + auto iter = ast::stmt(std::make_unique()); + iter.as_list->list.push_back(std::move(stmt->list.at(end - 1))); + iter.as_list->is_expr = true; + + begin--; // move begin from 'test' to 'init' + stmt->list.erase(stmt->list.begin() + begin); // remove 'init' + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + end -= 3; // move end to 'iter' ( minus 'init' & 'test' ) + stmt->list.erase(stmt->list.begin() + end); // remove 'iter' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto for_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + for_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(for_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(init), std::move(test), std::move(iter), ast::stmt(std::move(for_stmt)))); + new_stmt.as_for->vars = vars; + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_foreach(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(end - 1).loc().label(); + blk.loc_continue = stmt->list.at(end - 1).loc().label(); + + // collect local vars + std::vector vars; + while (stmt->list.at(begin - 1) == ast::kind::asm_create) + { + vars.push_back(stmt->list.at(begin - 1).as_asm_create->index); + stmt->list.erase(stmt->list.begin() + begin - 1); + begin--; + end--; + } + + std::reverse(vars.begin(), vars.end()); + + auto loc = stmt->list.at(begin - 2).loc(); + + auto init = ast::stmt(std::make_unique()); + init.as_list->list.push_back(std::move(stmt->list[begin-2])); + init.as_list->list.push_back(std::move(stmt->list[begin-1])); + auto stmt0 = std::move(stmt->list[begin+1]); + + begin -= 2; // move begin from 'test' to 'array' + stmt->list.erase(stmt->list.begin() + begin); // remove 'array' + stmt->list.erase(stmt->list.begin() + begin); // remove 'elem' + stmt->list.erase(stmt->list.begin() + begin); // remove 'test' + stmt->list.erase(stmt->list.begin() + begin); // remove 'set' + end -= 5; // move end to 'iter' ( minus 'array', 'elem', 'test' & 'set' ) + stmt->list.erase(stmt->list.begin() + end); // remove 'iter' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback + + if (stmt->list.size() > end && stmt->list.at(end) == ast::kind::asm_clear) + { + stmt->list.erase(stmt->list.begin() + end); // remove temp var 'array' + } + + auto use_key = true; + + if (stmt->list.size() > end && stmt->list.at(end) == ast::kind::asm_clear) + { + stmt->list.erase(stmt->list.begin() + end); // remove temp var 'key' + use_key = false; + } + + auto foreach_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + foreach_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(foreach_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, ast::stmt(std::move(foreach_stmt)), use_key)); + new_stmt.as_foreach->vars = vars; + new_stmt.as_foreach->pre_expr = std::move(init); + new_stmt.as_foreach->stmt0 = std::move(stmt0); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + +void decompiler::decompile_switch(const ast::stmt_list::ptr& stmt, std::size_t start) +{ + block blk; + blk.loc_continue = blocks_.back().loc_continue; + blk.loc_end = stmt->list.at(start).as_asm_switch->value; + + auto loc = stmt->list.at(start).loc(); + auto test = std::move(stmt->list.at(start).as_asm_switch->expr); + auto end_loc = stmt->list.at(start).as_asm_switch->value; + auto end = find_location_index(stmt, end_loc); + + blk.loc_break = (end == stmt->list.size() - 1) ? blocks_.back().loc_end : stmt->list.at(end + 1).loc().label(); + + // collect cases + auto casenum = std::atol(stmt->list.at(end).as_asm_endswitch->count.data()); + auto data = stmt->list.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(stmt, loc_str); + auto loc_pos = location(&filename_, std::stol(loc_str.substr(4), 0, 16)); + auto value = ast::expr(std::make_unique(loc_pos, data.at(idx + 1))); + auto list = std::make_unique(loc); + list->is_case = true; + auto case_stmt = ast::stmt(std::make_unique(loc_pos, std::move(value), std::move(list))); + stmt->list.insert(stmt->list.begin() + loc_idx, std::move(case_stmt)); + idx += 3; + } + else if (data.at(idx) == "default") + { + auto loc_str = data.at(idx + 1); + auto loc_idx = find_location_index(stmt, loc_str); + auto loc_pos = location(&filename_, std::stol(loc_str.substr(4), 0, 16)); + auto list = std::make_unique(loc); + list->is_case = true; + auto def_stmt = ast::stmt(std::make_unique(loc_pos, std::move(list))); + while (stmt->list.at(loc_idx) == ast::kind::stmt_case) + loc_idx++; + stmt->list.insert(stmt->list.begin() + loc_idx, std::move(def_stmt)); + idx += 2; + } + } + + end = find_location_index(stmt, end_loc); // update end + + while (stmt->list.size() > (end + 1) && stmt->list.at(end) != ast::kind::asm_endswitch) + end++; + + if (stmt->list.at(end) != ast::kind::asm_endswitch) + decomp_error("bad empty cases in switch block!"); + + end--; + stmt->list.erase(stmt->list.begin() + start); // remove 'switch' + stmt->list.erase(stmt->list.begin() + end); // remove 'endswitch' + + //decompile block + auto sw_stmt = std::make_unique(loc); + + for (auto i = start; i < end; i++) + { + sw_stmt->list.push_back(std::move(stmt->list[start])); + stmt->list.erase(stmt->list.begin() + start); + } + + blocks_.push_back(blk); + decompile_statements(sw_stmt); + blocks_.pop_back(); + + auto stmt_list = std::make_unique(loc); + auto current_case = ast::stmt(std::make_unique()); + + auto num = sw_stmt->list.size(); + for (auto i = 0u; i < num; i++) + { + auto& entry = sw_stmt->list[0]; + + if (entry == ast::kind::stmt_case || entry == ast::kind::stmt_default) + { + if (current_case.kind() != ast::kind::null) + { + stmt_list->list.push_back(std::move(current_case)); + } + + current_case = std::move(sw_stmt->list[0]); + sw_stmt->list.erase(sw_stmt->list.begin()); + } + else + { + if (current_case.kind() != ast::kind::null) + { + if (current_case == ast::kind::stmt_case) + { + current_case.as_case->stmt->list.push_back(std::move(sw_stmt->list[0])); + sw_stmt->list.erase(sw_stmt->list.begin()); + } + else + { + current_case.as_default->stmt->list.push_back(std::move(sw_stmt->list[0])); + sw_stmt->list.erase(sw_stmt->list.begin()); + } + } + else + { + decomp_error("missing case before stmt inside switch!"); + } + } + } + + if (current_case.kind() != ast::kind::null) + { + stmt_list->list.push_back(std::move(current_case)); + } + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), std::move(stmt_list))); + stmt->list.insert(stmt->list.begin() + start, std::move(new_stmt)); +} + +auto decompiler::find_location_reference(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end, const std::string& location) -> bool +{ + for (auto i = begin; i < end; i++) + { + const auto& entry = stmt->list.at(i); + + if (entry == ast::kind::asm_jump_cond && entry.as_cond->value == location) + { + return true; + } + else if (entry == ast::kind::asm_jump && entry.as_jump->value == location) + { + return true; + } + } + + return false; +} + +auto decompiler::find_location_index(const ast::stmt_list::ptr& stmt, const std::string& location) -> std::size_t +{ + auto index = 0u; + + if (location == blocks_.back().loc_end) + return stmt->list.size(); + + for (const auto& entry : stmt->list) + { + if (entry.loc().label() == location) + return index; + + index++; + } + + throw decomp_error("LOCATION NOT FOUND! (" + location + ")"); +} + +auto decompiler::last_location_index(const ast::stmt_list::ptr& stmt, std::size_t index) -> bool +{ + if (index == stmt->list.size() - 1) + return true; + + return false; +} + +void decompiler::process_stack(const ast::decl_thread::ptr& thread) +{ + auto blk = std::make_unique(); + + process_parameters(thread->params, blk); + process_stmt_list(thread->stmt, blk); +} + +void decompiler::process_parameters(const ast::expr_parameters::ptr& params, const block::ptr& blk) +{ + for (const auto& entry : params->list) + { + blk->local_vars.push_back({ entry->value, static_cast(std::stoi(entry->value.substr(4))), true }); + blk->local_vars_create_count++; + } +} + +void decompiler::process_stmt(const ast::stmt& stmt, const block::ptr& blk) +{ + switch (stmt.kind()) + { + case ast::kind::stmt_list: + process_stmt_list(stmt.as_list, blk); + break; + case ast::kind::stmt_expr: + process_stmt_expr(stmt.as_expr, blk); + break; + case ast::kind::stmt_call: + process_stmt_call(stmt.as_call, blk); + break; + case ast::kind::stmt_assign: + process_stmt_assign(stmt.as_assign, blk); + break; + case ast::kind::stmt_endon: + process_stmt_endon(stmt.as_endon, blk); + break; + case ast::kind::stmt_notify: + process_stmt_notify(stmt.as_notify, blk); + break; + case ast::kind::stmt_wait: + process_stmt_wait(stmt.as_wait, blk); + break; + case ast::kind::stmt_waittill: + process_stmt_waittill(stmt.as_waittill, blk); + break; + case ast::kind::stmt_waittillmatch: + process_stmt_waittillmatch(stmt.as_waittillmatch, blk); + break; + case ast::kind::stmt_if: + process_stmt_if(stmt.as_if, blk); + break; + case ast::kind::stmt_ifelse: + process_stmt_ifelse(stmt.as_ifelse, blk); + break; + case ast::kind::stmt_while: + process_stmt_while(stmt.as_while, blk); + break; + case ast::kind::stmt_dowhile: + process_stmt_dowhile(stmt.as_dowhile, blk); + break; + case ast::kind::stmt_for: + process_stmt_for(stmt.as_for, blk); + break; + case ast::kind::stmt_foreach: + process_stmt_foreach(stmt.as_foreach, blk); + break; + case ast::kind::stmt_switch: + process_stmt_switch(stmt.as_switch, blk); + break; + case ast::kind::stmt_break: + process_stmt_break(stmt.as_break, blk); + break; + case ast::kind::stmt_continue: + process_stmt_continue(stmt.as_continue, blk); + break; + case ast::kind::stmt_return: + process_stmt_return(stmt.as_return, blk); + break; + case ast::kind::asm_remove: + process_var_remove(stmt.as_asm_remove, blk); + break; + case ast::kind::asm_create: + { + auto expr = ast::expr(std::make_unique(stmt.as_asm_create->index)); + process_var_create(expr, blk, true); + break; + } + default: + break; + } +} + +void decompiler::process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk) +{ + for (const auto& entry : stmt->list) + { + process_stmt(entry, blk); + } + + auto i = 0u; + + while (i < stmt->list.size()) + { + auto type = stmt->list.at(i).kind(); + + if (type == ast::kind::asm_create || type == ast::kind::asm_remove) + { + stmt->list.erase(stmt->list.begin() + i); + continue; + } + + i++; + } +} + +void decompiler::process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr_increment(stmt->expr.as_increment, blk); + break; + case ast::kind::expr_decrement: + process_expr_decrement(stmt->expr.as_decrement, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr_assign(stmt->expr.as_assign, blk); + break; + default: + break; + } +} + +void decompiler::process_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_call: + process_expr_call(stmt->expr.as_call, blk); + break; + case ast::kind::expr_method: + process_expr_method(stmt->expr.as_method, blk); + break; + default: + break; + } +} + +void decompiler::process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk) +{ + switch (stmt->expr.kind()) + { + case ast::kind::expr_increment: + process_expr_increment(stmt->expr.as_increment, blk); + break; + case ast::kind::expr_decrement: + process_expr_decrement(stmt->expr.as_decrement, blk); + break; + case ast::kind::expr_assign_equal: + case ast::kind::expr_assign_add: + case ast::kind::expr_assign_sub: + case ast::kind::expr_assign_mul: + case ast::kind::expr_assign_div: + case ast::kind::expr_assign_mod: + case ast::kind::expr_assign_shift_left: + case ast::kind::expr_assign_shift_right: + case ast::kind::expr_assign_bitwise_or: + case ast::kind::expr_assign_bitwise_and: + case ast::kind::expr_assign_bitwise_exor: + process_expr_assign(stmt->expr.as_assign, blk); + break; + default: + break; + } +} + +void decompiler::process_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->event, blk); + process_expr(stmt->obj, blk); +} + +void decompiler::process_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk) +{ + process_expr_arguments(stmt->args, blk); + process_expr(stmt->event, blk); + process_expr(stmt->obj, blk); +} + +void decompiler::process_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->time, blk); +} + +void decompiler::process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->event ,blk); + process_expr(stmt->obj, blk); + + for (auto& entry : stmt->args->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk) +{ + process_expr_arguments(stmt->args, blk); + process_expr(stmt->event, blk); + process_expr(stmt->obj, blk); +} + +void decompiler::process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_stmt(stmt->stmt, stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk) +{ + std::vector childs; + auto abort = abort_t::abort_return; + + process_expr(stmt->test, blk); + + stmt->blk_if = std::make_unique(); + blk->transfer_decompiler(stmt->blk_if); + + process_stmt(stmt->stmt_if, stmt->blk_if); + + if (stmt->blk_if->abort <= abort_t::abort_return) + { + abort = stmt->blk_if->abort; + + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_if.get()); + } + + stmt->blk_else = std::make_unique(); + blk->transfer_decompiler(stmt->blk_else); + + process_stmt(stmt->stmt_else, stmt->blk_else); + + if (stmt->blk_else->abort <= abort) + { + abort = stmt->blk_else->abort; + + if (abort == abort_t::abort_none) + childs.push_back(stmt->blk_else.get()); + } + + if (blk->abort == abort_t::abort_none) + blk->abort = abort; + + blk->append(childs); + + if (stmt->stmt_if.as_list->list.size() == 1 && !stmt->stmt_if.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt_if = std::move(stmt->stmt_if.as_list->list.back()); + } + + if (stmt->stmt_else.as_list->list.size() == 1 && !stmt->stmt_else.as_list->list.at(0).as_node->is_special_stmt_noif()) + { + stmt->stmt_else = std::move(stmt->stmt_else.as_list->list.back()); + } +} + +void decompiler::process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_stmt(stmt->stmt, stmt->blk); + + std::vector childs({ stmt->blk.get() }); + + if (stmt->test.as_node->kind() == ast::kind::null) + blk->append_decompiler(stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_stmt(stmt->stmt, stmt->blk); + + std::vector childs({ stmt->blk.get() }); + + if (stmt->test.as_node->kind() == ast::kind::null) + blk->append_decompiler(stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk) +{ + process_stmt(stmt->init, blk); + + for (const auto& index : stmt->vars) + { + auto var = utils::string::va("var_%d", std::stoi(index)); + blk->local_vars.push_back({ var, static_cast(std::stoi(index)), true }); + blk->local_vars_create_count++; + } + + stmt->blk = std::make_unique(); + blk->transfer_decompiler(stmt->blk); + + process_expr(stmt->test, blk); + + process_stmt(stmt->stmt, stmt->blk); + + process_stmt(stmt->iter, blk); + + if (stmt->test == ast::kind::null) + blk->append_decompiler(stmt->blk); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } +} + +void decompiler::process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk) +{ + process_stmt(stmt->pre_expr, blk); + + for (const auto& index : stmt->vars) + { + auto var1 = utils::string::va("var_%d", std::stoi(index)); + blk->local_vars.push_back({ var1, static_cast(std::stoi(index)), true }); + blk->local_vars_create_count++; + } + + stmt->ctx = std::make_unique(); + blk->transfer_decompiler(stmt->ctx); + + process_stmt(stmt->stmt0, stmt->ctx); + process_stmt(stmt->stmt, stmt->ctx); + + if (stmt->stmt.as_list->list.size() == 1 && !stmt->stmt.as_list->list.at(0).as_node->is_special_stmt()) + { + stmt->stmt = std::move(stmt->stmt.as_list->list.back()); + } + + stmt->array_expr = std::move(stmt->pre_expr.as_list->list[0].as_assign->expr.as_assign->rvalue); + stmt->value_expr = std::move(stmt->stmt0.as_assign->expr.as_assign->lvalue); + stmt->key_expr = std::move(stmt->pre_expr.as_list->list[1].as_assign->expr.as_assign->lvalue); +} + +void decompiler::process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk) +{ + process_expr(stmt->test, blk); + + stmt->ctx = std::make_unique(); + blk->transfer_decompiler(stmt->ctx); + + process_stmt_cases(stmt->stmt, stmt->ctx); + + blk->append_decompiler(stmt->ctx, true); +} + +void decompiler::process_stmt_cases(const ast::stmt_list::ptr& stmt, const block::ptr& blk) +{ + std::vector childs; + bool has_default = false; + + for (const auto& entry : stmt->list) + { + if (entry == ast::kind::stmt_case) + { + entry.as_case->blk = std::make_unique(); + blk->transfer_decompiler(entry.as_case->blk); + + process_stmt_list(entry.as_case->stmt, entry.as_case->blk); + + if (entry.as_case->blk->abort == abort_t::abort_break) + { + childs.push_back(entry.as_case->blk.get()); + } + } + else if (entry == ast::kind::stmt_default) + { + has_default = true; + entry.as_default->blk = std::make_unique(); + blk->transfer_decompiler(entry.as_default->blk); + + process_stmt_list(entry.as_default->stmt, entry.as_default->blk); + + if (entry.as_default->blk->abort == abort_t::abort_break) + { + childs.push_back(entry.as_default->blk.get()); + } + } + } + + if (has_default) + { + blk->append(childs); + } +} + +void decompiler::process_stmt_break(const ast::stmt_break::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_break; + } +} + +void decompiler::process_stmt_continue(const ast::stmt_continue::ptr&, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_continue; + } +} + +void decompiler::process_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk) +{ + if (blk->abort == abort_t::abort_none) + { + blk->abort = abort_t::abort_return; + } + + if (stmt->expr != ast::kind::null) + { + process_expr(stmt->expr, blk); + } +} + +void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) +{ + switch (expr.kind()) + { + case ast::kind::expr_ternary: + process_expr_ternary(expr.as_ternary, blk); + break; + case ast::kind::expr_and: + process_expr_and(expr.as_and, blk); + break; + case ast::kind::expr_or: + process_expr_or(expr.as_or, blk); + break; + case ast::kind::expr_equality: + case ast::kind::expr_inequality: + case ast::kind::expr_less: + case ast::kind::expr_greater: + case ast::kind::expr_less_equal: + case ast::kind::expr_greater_equal: + case ast::kind::expr_bitwise_or: + case ast::kind::expr_bitwise_and: + case ast::kind::expr_bitwise_exor: + case ast::kind::expr_shift_left: + case ast::kind::expr_shift_right: + case ast::kind::expr_add: + case ast::kind::expr_sub: + case ast::kind::expr_mul: + case ast::kind::expr_div: + case ast::kind::expr_mod: + process_expr_binary(expr.as_binary, blk); + break; + case ast::kind::expr_complement: + process_expr_complement(expr.as_complement, blk); + break; + case ast::kind::expr_not: + process_expr_not(expr.as_not, blk); + break; + case ast::kind::expr_call: + process_expr_call(expr.as_call, blk); + break; + case ast::kind::expr_method: + process_expr_method(expr.as_method, blk); + break; + case ast::kind::expr_add_array: + process_expr_add_array(expr.as_add_array, blk); + break; + case ast::kind::expr_size: + process_expr_size(expr.as_size, blk); + break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; + case ast::kind::expr_vector: + process_expr_vector(expr.as_vector, blk); + break; + case ast::kind::asm_create: + process_var_create(expr, blk); + break; + case ast::kind::asm_access: + process_var_access(expr, blk); + break; + default: + break; + } +} + +void decompiler::process_expr_assign(ast::expr_assign::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->rvalue, blk); + process_expr(expr->lvalue, blk); + + if (expr->kind() == ast::kind::expr_assign_equal) + { + switch (expr->rvalue.kind()) + { + case ast::kind::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_bitwise_or->rvalue)); + break; + case ast::kind::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_bitwise_and->rvalue)); + break; + case ast::kind::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_bitwise_exor->rvalue)); + break; + case ast::kind::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_shift_left->rvalue)); + break; + case ast::kind::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_shift_right->rvalue)); + break; + case ast::kind::expr_add: + if (expr->lvalue == expr->rvalue.as_add->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_add->rvalue)); + break; + case ast::kind::expr_sub: + if (expr->lvalue == expr->rvalue.as_sub->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_sub->rvalue)); + break; + case ast::kind::expr_mul: + if (expr->lvalue == expr->rvalue.as_mul->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_mul->rvalue)); + break; + case ast::kind::expr_div: + if (expr->lvalue == expr->rvalue.as_div->lvalue) + expr = std::make_unique(std::move(expr->lvalue), std::move(expr->rvalue.as_div->rvalue)); + break; + case ast::kind::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_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); +} + +void decompiler::process_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); +} + +void decompiler::process_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->test, blk); + process_expr(expr->true_expr, blk); + process_expr(expr->false_expr, blk); +} + +void decompiler::process_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); + process_expr(expr->rvalue, blk); + + auto prec = expr->lvalue.as_node->precedence(); + + if (prec && prec < expr->precedence()) + { + expr->lvalue = ast::expr(std::make_unique(std::move(expr->lvalue))); + } + + prec = expr->rvalue.as_node->precedence(); + + if ((prec && prec < expr->precedence()) || (prec == expr->precedence() && expr->kind() == expr->rvalue.as_node->kind())) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); + process_expr(expr->rvalue, blk); + + auto prec = expr->lvalue.as_node->precedence(); + + if (prec && prec < expr->precedence()) + { + expr->lvalue = ast::expr(std::make_unique(std::move(expr->lvalue))); + } + + prec = expr->rvalue.as_node->precedence(); + + if ((prec && prec < expr->precedence()) || (prec == expr->precedence() && expr->kind() == expr->rvalue.kind())) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->lvalue, blk); + process_expr(expr->rvalue, blk); +} + +void decompiler::process_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->rvalue, blk); + + if (expr->rvalue.as_node->is_binary()) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->rvalue, blk); + + if (expr->rvalue.as_node->is_binary()) + { + expr->rvalue = ast::expr(std::make_unique(std::move(expr->rvalue))); + } +} + +void decompiler::process_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk) +{ + switch (expr->call.kind()) + { + case ast::kind::expr_pointer: + process_expr_call_pointer(expr->call.as_pointer, blk); + break; + case ast::kind::expr_function: + process_expr_call_function(expr->call.as_function, blk); + break; + default: + break; + } +} + +void decompiler::process_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk) +{ + switch (expr->call.kind()) + { + case ast::kind::expr_pointer: + process_expr_method_pointer(expr->call.as_pointer, expr->obj, blk); + break; + case ast::kind::expr_function: + process_expr_method_function(expr->call.as_function, expr->obj, blk); + break; + default: + break; + } +} + +void decompiler::process_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); + process_expr(expr->func, blk); +} + +void decompiler::process_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); +} + +void decompiler::process_expr_method_pointer(const ast::expr_pointer::ptr& expr, ast::expr& obj, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); + process_expr(obj, blk); + process_expr(expr->func, blk); +} + +void decompiler::process_expr_method_function(const ast::expr_function::ptr& expr, ast::expr& obj, const block::ptr& blk) +{ + process_expr_arguments(expr->args, blk); + process_expr(obj, blk); +} + +void decompiler::process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk) +{ + for (auto i = expr->list.size(); i > 0; i--) + { + process_expr(expr->list.at(i - 1), blk); + } +} + +void decompiler::process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk) +{ + for (auto& entry : expr->args->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->obj, blk); +} + +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->key, blk); + process_expr(expr->obj, blk); +} + +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->obj, blk); +} + +void decompiler::process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk) +{ + process_expr(vec->z, blk); + process_expr(vec->y, blk); + process_expr(vec->x, blk); +} + +void decompiler::process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt) +{ + if (fromstmt) + { + auto var = utils::string::va("var_%d", std::stoi(expr.as_asm_create->index)); + blk->local_vars.push_back({ var, static_cast(std::stoi(expr.as_asm_create->index)), true }); + blk->local_vars_create_count++; + } + else + { + for (const auto& entry : expr.as_asm_create->vars) + { + blk->local_vars.push_back({ utils::string::va("var_%d", std::stoi(entry)), static_cast(std::stoi(entry)), true }); + blk->local_vars_create_count++; + } + + auto var = utils::string::va("var_%d", std::stoi(expr.as_asm_create->index)); + blk->local_vars.push_back({ var, static_cast(std::stoi(expr.as_asm_create->index)), true }); + blk->local_vars_create_count++; + + expr = ast::expr(std::make_unique(var)); + } +} + +void decompiler::process_var_access(ast::expr& expr, const block::ptr& blk) +{ + if (blk->local_vars.size() <= std::stoul(expr.as_asm_access->index)) + { + std::cout << "WARNING: bad local var access\n"; + } + else + { + auto var = blk->local_vars.at(blk->local_vars.size() - 1 - std::stoi(expr.as_asm_access->index)).name; + expr = ast::expr(std::make_unique(var)); + } +} + +void decompiler::process_var_remove(const ast::asm_remove::ptr& expr, const block::ptr& blk) +{ + blk->local_vars_public_count = static_cast(blk->local_vars.size() - std::stoi(expr->index)); +} + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/decompiler.hpp b/src/experimental/s1c/xsk/decompiler.hpp new file mode 100644 index 00000000..67f4e863 --- /dev/null +++ b/src/experimental/s1c/xsk/decompiler.hpp @@ -0,0 +1,101 @@ +// Copyright 2022 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::s1c +{ + +class decompiler : public gsc::decompiler +{ + std::string filename_; + ast::program::ptr program_; + ast::decl_thread::ptr func_; + std::unordered_map labels_; + std::vector expr_labels_; + std::vector tern_labels_; + std::stack stack_; + std::vector blocks_; + bool in_waittill_; + +public: + auto output() -> std::vector; + void decompile(const std::string& file, std::vector& funcs); + +private: + void decompile_function(const function::ptr& func); + void decompile_instruction(const instruction::ptr& inst); + void decompile_expressions(const instruction::ptr& inst); + void decompile_statements(const ast::stmt_list::ptr& stmt); + void decompile_loops(const ast::stmt_list::ptr& stmt); + void decompile_switches(const ast::stmt_list::ptr& stmt); + void decompile_ifelses(const ast::stmt_list::ptr& stmt); + void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); + void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_ifelse_end(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_inf(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_loop(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_while(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_for(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_foreach(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); + void decompile_switch(const ast::stmt_list::ptr& stmt, std::size_t begin); + auto find_location_reference(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end, const std::string& location) -> bool; + auto find_location_index(const ast::stmt_list::ptr& stmt, const std::string& location) -> std::size_t; + auto last_location_index(const ast::stmt_list::ptr& stmt, std::size_t index) -> bool; + void process_stack(const ast::decl_thread::ptr& thread); + void process_parameters(const ast::expr_parameters::ptr& params, const block::ptr& blk); + void process_stmt(const ast::stmt& stmt, const block::ptr& blk); + void process_stmt_list(const ast::stmt_list::ptr& stmt, const block::ptr& blk); + void process_stmt_expr(const ast::stmt_expr::ptr& stmt, const block::ptr& blk); + void process_stmt_call(const ast::stmt_call::ptr& stmt, const block::ptr& blk); + void process_stmt_assign(const ast::stmt_assign::ptr& stmt, const block::ptr& blk); + void process_stmt_endon(const ast::stmt_endon::ptr& stmt, const block::ptr& blk); + void process_stmt_notify(const ast::stmt_notify::ptr& stmt, const block::ptr& blk); + void process_stmt_wait(const ast::stmt_wait::ptr& stmt, const block::ptr& blk); + void process_stmt_waittill(const ast::stmt_waittill::ptr& stmt, const block::ptr& blk); + void process_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt, const block::ptr& blk); + void process_stmt_if(const ast::stmt_if::ptr& stmt, const block::ptr& blk); + void process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt, const block::ptr& blk); + void process_stmt_while(const ast::stmt_while::ptr& stmt, const block::ptr& blk); + void process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt, const block::ptr& blk); + void process_stmt_for(const ast::stmt_for::ptr& stmt, const block::ptr& blk); + void process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const block::ptr& blk); + void process_stmt_switch(const ast::stmt_switch::ptr& stmt, const block::ptr& blk); + void process_stmt_cases(const ast::stmt_list::ptr& stmt, const block::ptr& blk); + void process_stmt_break(const ast::stmt_break::ptr& stmt, const block::ptr& blk); + void process_stmt_continue(const ast::stmt_continue::ptr& stmt, const block::ptr& blk); + void process_stmt_return(const ast::stmt_return::ptr& stmt, const block::ptr& blk); + void process_expr(ast::expr& expr, const block::ptr& blk); + void process_expr_assign(ast::expr_assign::ptr& expr, const block::ptr& blk); + void process_expr_increment(const ast::expr_increment::ptr& expr, const block::ptr& blk); + void process_expr_decrement(const ast::expr_decrement::ptr& expr, const block::ptr& blk); + void process_expr_ternary(const ast::expr_ternary::ptr& expr, const block::ptr& blk); + void process_expr_binary(const ast::expr_binary::ptr& expr, const block::ptr& blk); + void process_expr_and(const ast::expr_and::ptr& expr, const block::ptr& blk); + void process_expr_or(const ast::expr_or::ptr& expr, const block::ptr& blk); + void process_expr_complement(const ast::expr_complement::ptr& expr, const block::ptr& blk); + void process_expr_not(const ast::expr_not::ptr& expr, const block::ptr& blk); + void process_expr_call(const ast::expr_call::ptr& expr, const block::ptr& blk); + void process_expr_method(const ast::expr_method::ptr& expr, const block::ptr& blk); + void process_expr_call_pointer(const ast::expr_pointer::ptr& expr, const block::ptr& blk); + void process_expr_call_function(const ast::expr_function::ptr& expr, const block::ptr& blk); + void process_expr_method_pointer(const ast::expr_pointer::ptr& expr, ast::expr& obj, const block::ptr& blk); + void process_expr_method_function(const ast::expr_function::ptr& expr, ast::expr& obj, const block::ptr& blk); + void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); + void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); + void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); + void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); + void process_var_access(ast::expr& expr, const block::ptr& blk); + void process_var_remove(const ast::asm_remove::ptr& expr, const block::ptr& blk); +}; + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/disassembler.cpp b/src/experimental/s1c/xsk/disassembler.cpp new file mode 100644 index 00000000..a3617dbb --- /dev/null +++ b/src/experimental/s1c/xsk/disassembler.cpp @@ -0,0 +1,576 @@ +// Copyright 2022 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 "s1c.hpp" + +namespace xsk::gsc::s1c +{ + +auto disassembler::output() -> std::vector +{ + return std::move(functions_); +} + +auto disassembler::output_data() -> std::vector +{ + output_ = std::make_unique(0x100000); + + output_->write_string("// S1 GSC ASSEMBLY\n"); + output_->write_string("// Disassembled by https://github.com/xensik/gsc-tool\n"); + + for (const auto& func : functions_) + { + print_function(func); + } + + std::vector output; + + output.resize(output_->pos()); + std::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()); + const auto& func = functions_.back(); + + func->index = static_cast(script_->pos()); + func->size = stack_->read_endian(); + func->id = stack_->read_endian(); + func->name = func->id == 0 ? stack_->read_c_string() : resolver::token_name(static_cast(func->id)); + + dissasemble_function(func); + + func->labels = labels_; + labels_.clear(); + } + + resolve_local_functions(); +} + +void disassembler::dissasemble_function(const function::ptr& func) +{ + auto size = func->size; + + while (size > 0) + { + func->instructions.push_back(std::make_unique()); + + const auto& inst = func->instructions.back(); + inst->index = static_cast(script_->pos()); + inst->opcode = script_->read_endian(); + inst->size = opcode_size(inst->opcode); + + dissasemble_instruction(inst); + + size -= inst->size; + } +} + +void disassembler::dissasemble_instruction(const instruction::ptr& inst) +{ + switch (static_cast(inst->opcode)) + { + case opcode::OP_Return: + case opcode::OP_BoolNot: + case opcode::OP_CastBool: + case opcode::OP_inequality: + case opcode::OP_GetThisthread: + case opcode::OP_ClearLocalVariableFieldCached0: + case opcode::OP_checkclearparams: + case opcode::OP_CastFieldObject: + case opcode::OP_End: + case opcode::OP_size: + case opcode::OP_EmptyArray: + case opcode::OP_bit_and: + case opcode::OP_less_equal: + case opcode::OP_voidCodepos: +// case opcode::OP_ClearVariableField: + case opcode::OP_divide: + case opcode::OP_GetSelf: + case opcode::OP_SetLocalVariableFieldCached0: + case opcode::OP_plus: + case opcode::OP_BoolComplement: + case opcode::OP_ScriptMethodCallPointer: + case opcode::OP_inc: + case opcode::OP_clearparams: + case opcode::OP_EvalLocalVariableRefCached0: + case opcode::OP_ScriptFunctionCallPointer: + case opcode::OP_endon: + case opcode::OP_greater_equal: + case opcode::OP_GetSelfObject: + case opcode::OP_SetVariableField: + case opcode::OP_EvalLocalArrayRefCached0: + case opcode::OP_less: + case opcode::OP_GetGameRef: + case opcode::OP_waittillFrameEnd: + case opcode::OP_waitFrame: + case opcode::OP_SafeSetVariableFieldCached0: + case opcode::OP_GetLevel: + case opcode::OP_notify: + case opcode::OP_DecTop: + case opcode::OP_shift_left: + case opcode::OP_greater: + 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_GetZero: + case opcode::OP_wait: + case opcode::OP_minus: +// case opcode::OP_EvalNewLocalVariableRefCached0: + case opcode::OP_multiply: + case opcode::OP_mod: + case opcode::OP_GetGame: + case opcode::OP_waittill: + case opcode::OP_dec: + case opcode::OP_PreScriptCall: + case opcode::OP_GetAnim: + case opcode::OP_GetUndefined: + case opcode::OP_GetAnimObject: + case opcode::OP_GetLevelObject: + case opcode::OP_bit_ex_or: + case opcode::OP_equality: + case opcode::OP_ClearArray: + case opcode::OP_EvalArrayRef: + case opcode::OP_EvalArray: + case opcode::OP_vector: + case opcode::OP_bit_or: + case opcode::OP_AddArray: +// case opcode::OP_waittillmatch2: + case opcode::OP_shift_right: + break; + case opcode::OP_GetByte: + case opcode::OP_GetNegByte: + inst->data.push_back(utils::string::va("%i", script_->read_endian())); + break; + case opcode::OP_GetUnsignedShort: + case opcode::OP_GetNegUnsignedShort: + inst->data.push_back(utils::string::va("%i", script_->read_endian())); + break; + case opcode::OP_GetInteger: + inst->data.push_back(utils::string::va("%i", script_->read_endian())); + break; + case opcode::OP_GetFloat: + inst->data.push_back(utils::string::float_string(script_->read_endian())); + break; + case opcode::OP_GetVector: + inst->size += script_->align(4); + inst->data.push_back(utils::string::float_string(script_->read_endian())); + inst->data.push_back(utils::string::float_string(script_->read_endian())); + inst->data.push_back(utils::string::float_string(script_->read_endian())); + 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(), false)); + inst->data.push_back(utils::string::quote(stack_->read_c_string(), false)); + break; + case opcode::OP_GetAnimTree: + script_->seek(1); + inst->data.push_back(utils::string::quote(stack_->read_c_string(), false)); + break; + case opcode::OP_waittillmatch: + inst->data.push_back(utils::string::va("%i", script_->read_endian())); + 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_endian())); + 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: + 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_endian())); + break; + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalMethodCall: + disassemble_local_call(inst, false); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + disassemble_local_call(inst, true); + break; + case opcode::OP_GetFarFunction: + case opcode::OP_ScriptFarFunctionCall2: + case opcode::OP_ScriptFarFunctionCall: + case opcode::OP_ScriptFarMethodCall: + disassemble_far_call(inst, false); + break; + case opcode::OP_ScriptFarThreadCall: + case opcode::OP_ScriptFarChildThreadCall: + case opcode::OP_ScriptFarMethodThreadCall: + case opcode::OP_ScriptFarMethodChildThreadCall: + disassemble_far_call(inst, true); + break; + case opcode::OP_CallBuiltin: + disassemble_builtin_call(inst, false, true); + break; + case opcode::OP_CallBuiltinMethod: + 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: + 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: + disassemble_builtin_call(inst, true, false); + break; + case opcode::OP_JumpOnFalse: + case opcode::OP_JumpOnTrue: + case opcode::OP_JumpOnFalseExpr: + case opcode::OP_JumpOnTrueExpr: + disassemble_jump(inst, true, false); + break; + case opcode::OP_jumpback: + disassemble_jump(inst, false, true); + break; + case opcode::OP_jump: + disassemble_jump(inst, false, false); + break; + case opcode::OP_switch: + disassemble_switch(inst); + break; + case opcode::OP_endswitch: + disassemble_end_switch(inst); + break; + default: + throw disasm_error(utils::string::va("unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index)); + } +} + +void disassembler::disassemble_builtin_call(const instruction::ptr& inst, bool method, bool args) +{ + if (args) + { + inst->data.push_back(utils::string::va("%i", script_->read_endian())); + } + + const auto id = script_->read_endian(); + const auto name = method ? resolver::method_name(id) : resolver::function_name(id); + inst->data.emplace(inst->data.begin(), name); +} + +void disassembler::disassemble_local_call(const instruction::ptr& inst, bool thread) +{ + const auto offset = 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_endian())); + } +} + +void disassembler::disassemble_far_call(const instruction::ptr& inst, bool thread) +{ + script_->seek(3); + + if (thread) + { + inst->data.push_back(utils::string::va("%i", script_->read_endian())); + } + + const auto file_id = stack_->read_endian(); + const auto file_name = file_id == 0 ? stack_->read_c_string() : resolver::token_name(file_id); + const auto func_id = stack_->read_endian(); + const auto func_name = func_id == 0 ? stack_->read_c_string() : resolver::token_name(func_id); + + inst->data.emplace(inst->data.begin(), func_name); + inst->data.emplace(inst->data.begin(), file_name); +} + +void disassembler::disassemble_switch(const instruction::ptr& inst) +{ + const auto addr = inst->index + 4 + script_->read_endian(); + const auto label = utils::string::va("loc_%X", addr); + + inst->data.push_back(label); + labels_.insert({ addr, label }); +} + +void disassembler::disassemble_end_switch(const instruction::ptr& inst) +{ + const auto count = script_->read_endian(); + inst->data.push_back(utils::string::va("%i", count)); + + std::uint32_t index = inst->index + 3; + + if (count) + { + for (auto i = count; i > 0; i--) + { + const auto value = script_->read_endian(); + + if (value < 0x40000) + { + const auto data = stack_->read_c_string(); + + if (data.data()[0] != 0x01) + { + inst->data.push_back("case"); + inst->data.push_back(utils::string::quote(data, false)); + } + else + inst->data.push_back("default"); + } + else + { + inst->data.push_back("case"); + inst->data.push_back(utils::string::va("%i", (value - 0x800000) & 0xFFFFFF)); + } + + index += 4; + + const auto addr = disassemble_offset() + index; + const auto label = utils::string::va("loc_%X", addr); + + inst->data.push_back(label); + labels_.insert({ addr, label }); + + index += 3; + inst->size += 7; + } + } +} + +void disassembler::disassemble_field_variable(const instruction::ptr& inst) +{ + const auto id = script_->read_endian(); + std::string name; + + if (id > max_string_id) + { + auto temp = stack_->read_endian(); + name = temp == 0 ? stack_->read_c_string() : std::to_string(temp); + } + else + { + name = resolver::token_name(id); + } + + inst->data.push_back(name); +} + +void disassembler::disassemble_jump(const instruction::ptr& inst, bool expr, bool back) +{ + std::int32_t addr; + + if (expr) + { + addr = inst->index + 3 + script_->read_endian(); + } + else if (back) + { + addr = inst->index + 3 - script_->read_endian(); + } + else + { + addr = inst->index + 5 + script_->read_endian(); + } + + const auto label = utils::string::va("loc_%X", addr); + + inst->data.push_back(label); + labels_.insert({ addr, label }); +} + +auto disassembler::disassemble_offset() -> std::int32_t +{ + std::array bytes = {}; + + for (auto i = 0; i < 3; i++) + { + bytes[2 - i] = script_->read_endian(); + } + + auto offset = *reinterpret_cast(bytes.data()); + + offset = (offset << 8) >> 10; + + return offset; +} + +void disassembler::resolve_local_functions() +{ + for (const auto& func : functions_) + { + for (const auto& inst : func->instructions) + { + switch (static_cast(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[0] = 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 (const auto& func : functions_) + { + if (func->index == idx) + { + return func->name; + } + } + + throw disasm_error(utils::string::va("couldn't resolve function name at index '0x%04X'!", idx)); + } + + throw disasm_error(utils::string::va("\"%s\" is not valid function address!", index.data())); +} + +void disassembler::print_function(const function::ptr& func) +{ + output_->write_string("\n"); + output_->write_string(utils::string::va("sub_%s\n", func->name.data())); + + for (const 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())); + } + + print_instruction(inst); + } + + output_->write_string(utils::string::va("end_%s\n", func->name.data())); +} + +void disassembler::print_instruction(const instruction::ptr& inst) +{ + output_->write_string(utils::string::va("\t\t%s", resolver::opcode_name(inst->opcode).data())); + + switch (static_cast(inst->opcode)) + { + case opcode::OP_GetLocalFunction: + case opcode::OP_ScriptLocalFunctionCall: + case opcode::OP_ScriptLocalFunctionCall2: + case opcode::OP_ScriptLocalMethodCall: + output_->write_string(utils::string::va(" sub_%s", inst->data[0].data())); + break; + case opcode::OP_ScriptLocalThreadCall: + case opcode::OP_ScriptLocalChildThreadCall: + case opcode::OP_ScriptLocalMethodThreadCall: + case opcode::OP_ScriptLocalMethodChildThreadCall: + output_->write_string(utils::string::va(" sub_%s %s\n", inst->data[0].data(), inst->data[1].data())); + break; + case opcode::OP_endswitch: + 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: + for (auto& data : inst->data) + { + output_->write_string(utils::string::va(" %s", data.data())); + } + break; + } + + output_->write_string("\n"); +} + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/disassembler.hpp b/src/experimental/s1c/xsk/disassembler.hpp new file mode 100644 index 00000000..3614c449 --- /dev/null +++ b/src/experimental/s1c/xsk/disassembler.hpp @@ -0,0 +1,42 @@ +// Copyright 2022 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::s1c +{ + +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 function::ptr& func); + void dissasemble_instruction(const instruction::ptr& inst); + void disassemble_builtin_call(const instruction::ptr& inst, bool method, bool args); + void disassemble_local_call(const instruction::ptr& inst, bool thread); + void disassemble_far_call(const instruction::ptr& inst, bool thread); + void disassemble_switch(const instruction::ptr& inst); + void disassemble_end_switch(const instruction::ptr& inst); + void disassemble_field_variable(const instruction::ptr& inst); + void disassemble_jump(const instruction::ptr& inst, bool expr, bool back); + auto disassemble_offset() -> std::int32_t; + void resolve_local_functions(); + auto resolve_function(const std::string& index) -> std::string; + void print_function(const function::ptr& func); + void print_instruction(const instruction::ptr& inst); +}; + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/lexer.cpp b/src/experimental/s1c/xsk/lexer.cpp new file mode 100644 index 00000000..63a1e9ff --- /dev/null +++ b/src/experimental/s1c/xsk/lexer.cpp @@ -0,0 +1,849 @@ +// Copyright 2022 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 "s1c.hpp" +#include "parser.hpp" +#include "lexer.hpp" + +xsk::gsc::s1c::parser::symbol_type S1Clex(xsk::gsc::s1c::lexer& lexer) +{ + return lexer.lex(); +} + +namespace xsk::gsc::s1c +{ + +const std::unordered_map keyword_map +{{ + { "#define", parser::token::SH_DEFINE }, + { "#undef", parser::token::SH_UNDEF }, + { "#ifdef", parser::token::SH_IFDEF }, + { "#ifndef", parser::token::SH_IFNDEF }, + { "#if", parser::token::SH_IF }, + { "#elif", parser::token::SH_ELIF }, + { "#else", parser::token::SH_ELSE }, + { "#endif", parser::token::SH_ENDIF }, + { "#inline", parser::token::INLINE }, + { "#include", parser::token::INCLUDE }, + { "#using_animtree", parser::token::USINGTREE }, + { "#animtree", parser::token::ANIMTREE }, + { "endon", parser::token::ENDON }, + { "notify", parser::token::NOTIFY }, + { "wait", parser::token::WAIT }, + { "waittill", parser::token::WAITTILL }, + { "waittillmatch", parser::token::WAITTILLMATCH }, + { "waittillframeend", parser::token::WAITTILLFRAMEEND }, + { "waitframe", parser::token::WAITFRAME }, + { "if", parser::token::IF }, + { "else", parser::token::ELSE }, + { "do", parser::token::DO }, + { "while", parser::token::WHILE }, + { "for", parser::token::FOR }, + { "foreach", parser::token::FOREACH }, + { "in", parser::token::IN }, + { "switch", parser::token::SWITCH }, + { "case", parser::token::CASE }, + { "default", parser::token::DEFAULT }, + { "break", parser::token::BREAK }, + { "continue", parser::token::CONTINUE }, + { "return", parser::token::RETURN }, + { "breakpoint", parser::token::BREAKPOINT }, + { "prof_begin", parser::token::PROFBEGIN }, + { "prof_end", parser::token::PROFEND }, + { "thread", parser::token::THREAD }, + { "childthread", parser::token::CHILDTHREAD }, + { "thisthread", parser::token::THISTHREAD }, + { "call", parser::token::CALL }, + { "true", parser::token::TRUE }, + { "false", parser::token::FALSE }, + { "undefined", parser::token::UNDEFINED }, + { "size", parser::token::SIZE }, + { "game", parser::token::GAME }, + { "self", parser::token::SELF }, + { "anim", parser::token::ANIM }, + { "level", parser::token::LEVEL }, +}}; + +buffer::buffer() : length(0) +{ + data = static_cast(std::malloc(max_buf_size)); +} + +buffer::~buffer() +{ + if (data) std::free(data); +} + +bool buffer::push(char c) +{ + if (length >= max_buf_size) + return false; + + data[length++] = c; + return true; +} + +reader::reader() : buffer_pos(0), bytes_remaining(0), last_byte(0), current_byte(0), state(reader::end) +{ + +} + +void reader::init(const char* data, size_t size) +{ + if (data && size) + { + state = reader::ok; + buffer_pos = data; + bytes_remaining = static_cast(size); + last_byte = 0; + current_byte = *data; + } + else + { + state = reader::end; + buffer_pos = 0; + bytes_remaining = 0; + last_byte = 0; + current_byte = 0; + } +} + +void reader::advance() +{ + ++buffer_pos; + + if (bytes_remaining-- == 1) + { + state = reader::end; + bytes_remaining = 0; + last_byte = current_byte; + current_byte = 0; + } + else + { + last_byte = current_byte; + current_byte = *buffer_pos; + } +} + +lexer::lexer(build mode, const std::string& name, const char* data, size_t size) : loc_(location(&name)), + locs_(std::stack()), readers_(std::stack()), header_top_(0), mode_(mode), indev_(false), clean_(true) +{ + reader_.init(data, size); +} + +void lexer::push_header(const std::string& file) +{ + try + { + if (header_top_++ >= 10) + throw comp_error(loc_, "maximum gsh depth exceeded '10'"); + + auto data = resolver::file_data(file + ".gsh"); + + readers_.push(reader_); + locs_.push(loc_); + loc_.initialize(std::get<0>(data)); + reader_.init(std::get<1>(data), std::get<2>(data)); + clean_ = true; + } + catch (const std::exception& e) + { + throw error("parsing header file '" + file + "': " + e.what()); + } +} + +void lexer::pop_header() +{ + header_top_--; + loc_ = locs_.top(); + locs_.pop(); + reader_ = readers_.top(); + readers_.pop(); +} + +void lexer::ban_header(const location& loc) +{ + if (header_top_ > 0) + { + throw comp_error(loc, "not allowed inside a gsh file"); + } +} + +auto lexer::lex() -> parser::symbol_type +{ + buffer_.length = 0; + state_ = state::start; + + while (true) + { + const auto& state = reader_.state; + auto& last = reader_.last_byte; + auto& curr = reader_.current_byte; + auto path = false; + loc_.step(); + + if (state == reader::end) + { + if (indev_) + throw comp_error(loc_, "unmatched devblock start ('/#')"); + + if (header_top_ > 0) + pop_header(); + else + return parser::make_S1CEOF(loc_); + } + + if (clean_ && last != 0 && last != ' ' && last != '\t' && last != '\n') + clean_ = false; + + advance(); + + switch (last) + { + case ' ': + case '\t': + case '\r': + loc_.step(); + continue; + case '\n': + loc_.lines(); + loc_.step(); + clean_ = true; + continue; + case '\\': + throw comp_error(loc_, "invalid token ('\\')"); + case '/': + if (curr != '=' && curr != '#' && curr != '@' && curr != '*' && curr != '/') + return parser::make_DIV(loc_); + + advance(); + + if (last == '=') + return parser::make_ASSIGN_DIV(loc_); + + if (last == '#') + { + if (indev_) + throw comp_error(loc_, "cannot recurse devblock ('/#')"); + + if (mode_ == build::dev) + { + indev_ = true; + return parser::make_DEVBEGIN(loc_); + } + else + { + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched devblock start ('/#')"); + + if (curr == '\n') + { + loc_.lines(); + loc_.step(); + } + else if (last == '#' && curr == '/') + { + advance(); + break; + } + + advance(); + } + } + } + else if (last == '@') + { + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched script doc comment start ('/@')"); + + if (curr == '\n') + { + loc_.lines(); + loc_.step(); + } + else if (last == '@' && curr == '/') + { + advance(); + break; + } + + advance(); + } + } + else if (last == '*') + { + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched multiline comment start ('/*')"); + + if (curr == '\n') + { + loc_.lines(); + loc_.step(); + } + else if (last == '*' && curr == '/') + { + advance(); + break; + } + + advance(); + } + } + else if (last == '/') + { + while (true) + { + if (state == reader::end) + break; + + if (curr == '\n') + break; + + advance(); + } + } + continue; + case '#': + if (curr == '/') + { + if (!indev_) + throw comp_error(loc_, "unmatched devblock end ('#/')"); + + advance(); + indev_ = false; + return parser::make_DEVEND(loc_); + } + + buffer_.push(last); + advance(); + + while (state == reader::ok) + { + if (last != ' ' || last != '\t') + break; + + advance(); + } + + if (state == reader::end || !((last > 64 && last < 91) || (last > 96 && last < 123))) + throw comp_error(loc_, "invalid preprocessor directive ('#')"); + + state_ = state::preprocessor; + goto lex_name; + case '*': + if (curr != '=' && curr != '/') + return parser::make_MUL(loc_); + + advance(); + + if (last == '=') + return parser::make_ASSIGN_MUL(loc_); + + throw comp_error(loc_, "unmatched multiline comment end ('*/')"); + case '"': + state_ = state::string; + goto lex_string; + case '.': + if (curr < '0' || curr > '9') + return parser::make_DOT(loc_); + goto lex_number; + case '(': + return parser::make_LPAREN(loc_); + case ')': + return parser::make_RPAREN(loc_); + case '{': + return parser::make_LBRACE(loc_); + case '}': + return parser::make_RBRACE(loc_); + case '[': + return parser::make_LBRACKET(loc_); + case ']': + return parser::make_RBRACKET(loc_); + case ',': + return parser::make_COMMA(loc_); + case ';': + return parser::make_SEMICOLON(loc_); + case ':': + if (curr != ':') + return parser::make_COLON(loc_); + + advance(); + return parser::make_DOUBLECOLON(loc_); + case '?': + return parser::make_QMARK(loc_); + case '=': + if (curr != '=') + return parser::make_ASSIGN(loc_); + + advance(); + return parser::make_EQUALITY(loc_); + case '+': + if (curr != '+' && curr != '=') + return parser::make_ADD(loc_); + + advance(); + + if (last == '+') + return parser::make_INCREMENT(loc_); + + return parser::make_ASSIGN_ADD(loc_); + case '-': + if (curr != '-' && curr != '=') + return parser::make_SUB(loc_); + + advance(); + + if (last == '-') + return parser::make_DECREMENT(loc_); + + return parser::make_ASSIGN_SUB(loc_); + case '%': + if (curr != '=') + return parser::make_MOD(loc_); + + advance(); + + return parser::make_ASSIGN_MOD(loc_); + case '|': + if (curr != '|' && curr != '=') + return parser::make_BITWISE_OR(loc_); + + advance(); + + if (last == '|') + return parser::make_OR(loc_); + + return parser::make_ASSIGN_BW_OR(loc_); + case '&': + if (curr != '&' && curr != '=' && curr != '"') + return parser::make_BITWISE_AND(loc_); + + advance(); + + if (last == '&') + return parser::make_AND(loc_); + + if (last == '=') + return parser::make_ASSIGN_BW_AND(loc_); + + state_ = state::localize; + goto lex_string; + case '^': + if (curr != '=') + return parser::make_BITWISE_EXOR(loc_); + + advance(); + return parser::make_ASSIGN_BW_EXOR(loc_); + case '!': + if (curr != '=') + return parser::make_NOT(loc_); + + advance(); + return parser::make_INEQUALITY(loc_); + case '~': + return parser::make_COMPLEMENT(loc_); + case '<': + if (curr != '<' && curr != '=') + return parser::make_LESS(loc_); + + advance(); + if (last == '=') + return parser::make_LESS_EQUAL(loc_); + + if (curr != '=') + return parser::make_LSHIFT(loc_); + + advance(); + return parser::make_ASSIGN_LSHIFT(loc_); + case '>': + if (curr != '>' && curr != '=') + return parser::make_GREATER(loc_); + + advance(); + + if (last == '=') + return parser::make_GREATER_EQUAL(loc_); + + if (curr != '=') + return parser::make_RSHIFT(loc_); + + advance(); + return parser::make_ASSIGN_RSHIFT(loc_); + default: + if (last >= '0' && last <= '9') + goto lex_number; + else if (last == '_' || (last >= 'A' && last <= 'Z') || (last >= 'a' && last <= 'z')) + goto lex_name; + + throw comp_error(loc_, utils::string::va("bad token: \'%c\'", last)); + } + +lex_string: + while (true) + { + if (state == reader::end) + throw comp_error(loc_, "unmatched string start ('\"')"); + + if (curr == '"') + { + advance(); + break; + } + + if (curr == '\n') + throw comp_error(loc_, "unterminated string literal"); + + if (curr == '\\') + { + advance(); + + if (state == reader::end) + throw comp_error(loc_, "invalid token ('\')"); + + char c = curr; + switch (curr) + { + case 't': c = '\t'; break; + case 'r': c = '\r'; break; + case 'n': c = '\n'; break; + case '"': c = '\"'; break; + case '\\': c = '\\'; break; + default: break; + } + + if (!buffer_.push(c)) + throw comp_error(loc_, "max string size exceeded"); + } + else if (!buffer_.push(curr)) + throw comp_error(loc_, "max string size exceeded"); + + advance(); + } + + if (state_ == state::localize) + return parser::make_ISTRING(std::string(buffer_.data, buffer_.length), loc_); + + return parser::make_STRING(std::string(buffer_.data, buffer_.length), loc_); + +lex_name: + buffer_.push(last); + + while (true) + { + if (state == reader::end) + break; + + if (!(curr == '\\' || curr == '_' || (curr > 64 && curr < 91) || (curr > 96 && curr < 123) || (curr > 47 && curr < 58))) + break; + + if (curr == '\\') + { + if (last == '\\') + throw comp_error(loc_, "invalid path '\\\\'"); + + path = true; + if (!buffer_.push('/')) + throw comp_error(loc_, "max string size exceeded"); + } + else if (!buffer_.push(curr)) + throw comp_error(loc_, "max string size exceeded"); + + advance(); + } + + if (state_ == state::preprocessor) + { + auto token = parser::token::S1CUNDEF; + + if (buffer_.length < 16) + { + const auto itr = keyword_map.find(std::string_view(buffer_.data, buffer_.length)); + + if (itr != keyword_map.end()) + { + if (itr->second > parser::token::SH_ENDIF) + return parser::symbol_type(itr->second, loc_); + + token = itr->second; + } + } + + preprocessor_run(token); + + state_ = state::start; + continue; + } + else + { + if (buffer_.length < 17) + { + const auto itr = keyword_map.find(std::string_view(buffer_.data, buffer_.length)); + + if (itr != keyword_map.end()) + return parser::symbol_type(itr->second, loc_); + } + + if (path) + { + if (buffer_.data[buffer_.length - 1] == '/') + throw comp_error(loc_, "invalid path end '\\'"); + + return parser::make_PATH(resolver::make_token(std::string_view(buffer_.data, buffer_.length)), loc_); + } + + return parser::make_IDENTIFIER(resolver::make_token(std::string_view(buffer_.data, buffer_.length)), loc_); + } + +lex_number: + if (last == '.' || last != '0' || (last == '0' && (curr != 'o' && curr != 'b' && curr != 'x'))) + { + buffer_.push(last); + + auto dot = last == '.' ? 1 : 0; + auto flt = 0; + + while (true) + { + if (state == reader::end) + break; + + if (curr == '\'' && (last == '\'' || last == 'f' || last == '.')) + throw comp_error(loc_, "invalid number literal"); + + if ((curr == '.' || curr == 'f') && last == '\'') + throw comp_error(loc_, "invalid number literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (curr == 'f') + flt++; + else if (curr == '.') + dot++; + else if (!(curr > 47 && curr < 58)) + break; + + if (!buffer_.push(curr)) + throw comp_error(loc_, "number literal size exceeded"); + + advance(); + } + + if (last == '\'') + throw comp_error(loc_, "invalid number literal"); + + if (dot > 1 || flt > 1 || (flt && buffer_.data[buffer_.length - 1] != 'f')) + throw comp_error(loc_, "invalid number literal"); + + if (dot || flt) + return parser::make_FLOAT(std::string(buffer_.data, buffer_.length), loc_); + + return parser::make_INTEGER(std::string(buffer_.data, buffer_.length), loc_); + } + else if (curr == 'o') + { + advance(); + + while (true) + { + if (state == reader::end) + break; + + if ((curr == '\'' && (last == '\'' || last == 'o')) || (curr == 'o' && last == '\'')) + throw comp_error(loc_, "invalid octal literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (!(curr > 47 && curr < 56)) + break; + + if (!buffer_.push(curr)) + throw error("gsc lexer: out of memory!"); + + advance(); + } + + if (last == '\'' || buffer_.length <= 0) + throw comp_error(loc_, "invalid octal literal"); + + return parser::make_INTEGER(utils::string::oct_to_dec(buffer_.data), loc_); + } + else if (curr == 'b') + { + buffer_.push(last); + buffer_.push(curr); + advance(); + + while (true) + { + if (state == reader::end) + break; + + if ((curr == '\'' && (last == '\'' || last == 'b')) || (curr == 'b' && last == '\'')) + throw comp_error(loc_, "invalid binary literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (curr != '0' && curr != '1') + break; + + if (!buffer_.push(curr)) + throw comp_error(loc_, "number literal size exceeded"); + + advance(); + } + + if (last == '\'' || buffer_.length < 3) + throw comp_error(loc_, "invalid binary literal"); + + return parser::make_INTEGER(utils::string::bin_to_dec(buffer_.data), loc_); + } + else if (curr == 'x') + { + buffer_.push(last); + buffer_.push(curr); + advance(); + + while (true) + { + if (state == reader::end) + break; + + if ((curr == '\'' && (last == '\'' || last == 'x')) || (curr == 'x' && last == '\'')) + throw comp_error(loc_, "invalid hexadecimal literal"); + + if (curr == '\'') + { + advance(); + continue; + } + + if (!((curr > 47 && curr < 58) || (curr > 64 && curr < 71) || (curr > 96 && curr < 103))) + break; + + if (!buffer_.push(curr)) + throw error("gsc lexer: out of memory!"); + + advance(); + } + + if (last == '\'' || buffer_.length < 3) + throw comp_error(loc_, "invalid hexadecimal literal"); + + return parser::make_INTEGER(utils::string::hex_to_dec(buffer_.data), loc_); + } + + throw error("UNEXPECTED LEXER INTERNAL ERROR!"); + } +} + +void lexer::advance() +{ + reader_.advance(); + loc_.end.column++; + + if (reader_.current_byte == '\\') [[unlikely]] + preprocessor_wrap(); +} + +void lexer::preprocessor_wrap() +{ + while (reader_.current_byte == '\\') + { + if (reader_.bytes_remaining == 1) + throw comp_error(loc_, "invalid token ('\\')"); + + if (reader_.buffer_pos[1] != '\r' && reader_.buffer_pos[1] != '\n') + break; + + if (reader_.buffer_pos[1] == '\r') + { + if (reader_.bytes_remaining <= 3 || reader_.buffer_pos[2] != '\n') + throw comp_error(loc_, "invalid token ('\\')"); + + reader_.buffer_pos += 3; + reader_.bytes_remaining -= 3; + } + + if ((reader_.buffer_pos[1] == '\n')) + { + if (reader_.bytes_remaining == 2) + throw comp_error(loc_, "invalid token ('\\')"); + + reader_.buffer_pos += 2; + reader_.bytes_remaining -= 2; + } + + if (reader_.bytes_remaining == 0) + { + reader_.state = reader::end; + reader_.current_byte = 0; + } + else + { + reader_.current_byte = *reader_.buffer_pos; + } + + loc_.lines(); + loc_.step(); + } +} + +void lexer::preprocessor_run(parser::token::token_kind_type token) +{ + if (!clean_) + throw comp_error(loc_, "invalid token ('#')"); + + switch (token) + { + case parser::token::SH_DEFINE: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_UNDEF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_IFDEF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_IFNDEF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_IF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_ELIF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_ELSE: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + case parser::token::SH_ENDIF: + throw comp_error(loc_, "unimplemented preprocessor directive"); + break; + default: + throw comp_error(loc_, "unknown preprocessor directive"); + } +} + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/lexer.hpp b/src/experimental/s1c/xsk/lexer.hpp new file mode 100644 index 00000000..03853d2d --- /dev/null +++ b/src/experimental/s1c/xsk/lexer.hpp @@ -0,0 +1,78 @@ +// Copyright 2022 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::s1c +{ + +constexpr size_t max_buf_size = 0x2000; + +struct buffer +{ + char* data; + size_t length; + + buffer(); + ~buffer(); + bool push(char c); +}; + +struct reader +{ + enum state_type : std::uint8_t { end, ok }; + + const char* buffer_pos; + std::uint32_t bytes_remaining; + char last_byte; + char current_byte; + state_type state; + + reader(); + + reader(const reader& obj) + { + std::memcpy(this, &obj, sizeof(reader)); + } + + reader& operator=(const reader& obj) + { + std::memcpy(this, &obj, sizeof(reader)); + return *this; + } + + void init(const char* data, size_t size); + void advance(); +}; + +class lexer +{ + enum class state : std::uint8_t { start, string, localize, preprocessor }; + + reader reader_; + buffer buffer_; + location loc_; + std::stack locs_; + std::stack readers_; + std::uint32_t header_top_; + state state_; + build mode_; + bool indev_; + bool clean_; + +public: + lexer(build mode, const std::string& name, const char* data, size_t size); + auto lex() -> parser::symbol_type; + void push_header(const std::string& file); + void pop_header(); + void ban_header(const location& loc); + +private: + void advance(); + void preprocessor_wrap(); + void preprocessor_run(parser::token::token_kind_type token); +}; + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1c/xsk/parser.cpp b/src/experimental/s1c/xsk/parser.cpp new file mode 100644 index 00000000..b02dd770 --- /dev/null +++ b/src/experimental/s1c/xsk/parser.cpp @@ -0,0 +1,4733 @@ +// A Bison parser, made by GNU Bison 3.8.2. + +// 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 38 "parser.ypp" + +#include "stdafx.hpp" +#include "parser.hpp" +#include "lexer.hpp" +using namespace xsk::gsc; +xsk::gsc::s1c::parser::symbol_type S1Clex(xsk::gsc::s1c::lexer& lexer); + +#line 47 "parser.cpp" + +// Take the name prefix into account. +#define yylex S1Clex + + + +#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 S1CDEBUG + +// 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 // !S1CDEBUG + +# 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 // !S1CDEBUG + +#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 s1c { +#line 149 "parser.cpp" + + /// Build a parser object. + parser::parser (xsk::gsc::s1c::lexer& lexer_yyarg, xsk::gsc::ast::program::ptr& ast_yyarg) +#if S1CDEBUG + : yydebug_ (false), + yycdebug_ (&std::cerr), +#else + : +#endif + yy_lac_established_ (false), + lexer (lexer_yyarg), + ast (ast_yyarg) + {} + + parser::~parser () + {} + + parser::syntax_error::~syntax_error () YY_NOEXCEPT YY_NOTHROW + {} + + /*---------. + | symbol. | + `---------*/ + + + + // 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.YY_MOVE_OR_COPY< ast::call > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.YY_MOVE_OR_COPY< ast::decl > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.YY_MOVE_OR_COPY< ast::decl_constant::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.YY_MOVE_OR_COPY< ast::decl_thread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.YY_MOVE_OR_COPY< ast::decl_usingtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.YY_MOVE_OR_COPY< ast::expr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.YY_MOVE_OR_COPY< ast::expr_add_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.YY_MOVE_OR_COPY< ast::expr_anim::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.YY_MOVE_OR_COPY< ast::expr_animation::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.YY_MOVE_OR_COPY< ast::expr_animtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.YY_MOVE_OR_COPY< ast::expr_arguments::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.YY_MOVE_OR_COPY< ast::expr_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.YY_MOVE_OR_COPY< ast::expr_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.YY_MOVE_OR_COPY< ast::expr_complement::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.YY_MOVE_OR_COPY< ast::expr_empty_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.YY_MOVE_OR_COPY< ast::expr_false::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.YY_MOVE_OR_COPY< ast::expr_field::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.YY_MOVE_OR_COPY< ast::expr_float::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.YY_MOVE_OR_COPY< ast::expr_game::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.YY_MOVE_OR_COPY< ast::expr_identifier::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.YY_MOVE_OR_COPY< ast::expr_integer::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.YY_MOVE_OR_COPY< ast::expr_istring::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.YY_MOVE_OR_COPY< ast::expr_level::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.YY_MOVE_OR_COPY< ast::expr_method::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.YY_MOVE_OR_COPY< ast::expr_negate::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.YY_MOVE_OR_COPY< ast::expr_not::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.YY_MOVE_OR_COPY< ast::expr_parameters::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.YY_MOVE_OR_COPY< ast::expr_paren::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.YY_MOVE_OR_COPY< ast::expr_path::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.YY_MOVE_OR_COPY< ast::expr_reference::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.YY_MOVE_OR_COPY< ast::expr_self::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.YY_MOVE_OR_COPY< ast::expr_size::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.YY_MOVE_OR_COPY< ast::expr_string::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.YY_MOVE_OR_COPY< ast::expr_thisthread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.YY_MOVE_OR_COPY< ast::expr_true::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.YY_MOVE_OR_COPY< ast::expr_tuple::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.YY_MOVE_OR_COPY< ast::expr_undefined::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.YY_MOVE_OR_COPY< ast::expr_vector::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.YY_MOVE_OR_COPY< ast::include::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.YY_MOVE_OR_COPY< ast::program::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.YY_MOVE_OR_COPY< ast::stmt > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.YY_MOVE_OR_COPY< ast::stmt_assign::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.YY_MOVE_OR_COPY< ast::stmt_break::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.YY_MOVE_OR_COPY< ast::stmt_breakpoint::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.YY_MOVE_OR_COPY< ast::stmt_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.YY_MOVE_OR_COPY< ast::stmt_case::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.YY_MOVE_OR_COPY< ast::stmt_continue::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.YY_MOVE_OR_COPY< ast::stmt_default::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.YY_MOVE_OR_COPY< ast::stmt_dev::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.YY_MOVE_OR_COPY< ast::stmt_dowhile::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.YY_MOVE_OR_COPY< ast::stmt_endon::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.YY_MOVE_OR_COPY< ast::stmt_expr::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.YY_MOVE_OR_COPY< ast::stmt_for::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.YY_MOVE_OR_COPY< ast::stmt_foreach::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.YY_MOVE_OR_COPY< ast::stmt_if::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.YY_MOVE_OR_COPY< ast::stmt_ifelse::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.YY_MOVE_OR_COPY< ast::stmt_list::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.YY_MOVE_OR_COPY< ast::stmt_notify::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.YY_MOVE_OR_COPY< ast::stmt_prof_begin::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.YY_MOVE_OR_COPY< ast::stmt_prof_end::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.YY_MOVE_OR_COPY< ast::stmt_return::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.YY_MOVE_OR_COPY< ast::stmt_switch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.YY_MOVE_OR_COPY< ast::stmt_wait::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.YY_MOVE_OR_COPY< ast::stmt_waitframe::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.YY_MOVE_OR_COPY< ast::stmt_waittill::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.YY_MOVE_OR_COPY< ast::stmt_waittillframeend::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.YY_MOVE_OR_COPY< ast::stmt_waittillmatch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.YY_MOVE_OR_COPY< ast::stmt_while::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.YY_MOVE_OR_COPY< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< ast::stmt_waitframe::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.copy< ast::call > (that.value); + break; + + case symbol_kind::S_declaration: // declaration + value.copy< ast::decl > (that.value); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.copy< ast::decl_constant::ptr > (that.value); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.copy< ast::decl_thread::ptr > (that.value); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.copy< ast::decl_usingtree::ptr > (that.value); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.copy< ast::expr > (that.value); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.copy< ast::expr_add_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.copy< ast::expr_anim::ptr > (that.value); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.copy< ast::expr_animation::ptr > (that.value); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.copy< ast::expr_animtree::ptr > (that.value); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.copy< ast::expr_arguments::ptr > (that.value); + break; + + case symbol_kind::S_expr_array: // expr_array + value.copy< ast::expr_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_call: // expr_call + value.copy< ast::expr_call::ptr > (that.value); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.copy< ast::expr_complement::ptr > (that.value); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.copy< ast::expr_empty_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_false: // expr_false + value.copy< ast::expr_false::ptr > (that.value); + break; + + case symbol_kind::S_expr_field: // expr_field + value.copy< ast::expr_field::ptr > (that.value); + break; + + case symbol_kind::S_expr_float: // expr_float + value.copy< ast::expr_float::ptr > (that.value); + break; + + case symbol_kind::S_expr_game: // expr_game + value.copy< ast::expr_game::ptr > (that.value); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.copy< ast::expr_identifier::ptr > (that.value); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.copy< ast::expr_integer::ptr > (that.value); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.copy< ast::expr_istring::ptr > (that.value); + break; + + case symbol_kind::S_expr_level: // expr_level + value.copy< ast::expr_level::ptr > (that.value); + break; + + case symbol_kind::S_expr_method: // expr_method + value.copy< ast::expr_method::ptr > (that.value); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.copy< ast::expr_negate::ptr > (that.value); + break; + + case symbol_kind::S_expr_not: // expr_not + value.copy< ast::expr_not::ptr > (that.value); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.copy< ast::expr_parameters::ptr > (that.value); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.copy< ast::expr_paren::ptr > (that.value); + break; + + case symbol_kind::S_expr_path: // expr_path + value.copy< ast::expr_path::ptr > (that.value); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.copy< ast::expr_reference::ptr > (that.value); + break; + + case symbol_kind::S_expr_self: // expr_self + value.copy< ast::expr_self::ptr > (that.value); + break; + + case symbol_kind::S_expr_size: // expr_size + value.copy< ast::expr_size::ptr > (that.value); + break; + + case symbol_kind::S_expr_string: // expr_string + value.copy< ast::expr_string::ptr > (that.value); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.copy< ast::expr_thisthread::ptr > (that.value); + break; + + case symbol_kind::S_expr_true: // expr_true + value.copy< ast::expr_true::ptr > (that.value); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.copy< ast::expr_tuple::ptr > (that.value); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.copy< ast::expr_undefined::ptr > (that.value); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.copy< ast::expr_vector::ptr > (that.value); + break; + + case symbol_kind::S_include: // include + value.copy< ast::include::ptr > (that.value); + break; + + case symbol_kind::S_program: // program + value.copy< ast::program::ptr > (that.value); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.copy< ast::stmt > (that.value); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.copy< ast::stmt_assign::ptr > (that.value); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.copy< ast::stmt_break::ptr > (that.value); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.copy< ast::stmt_breakpoint::ptr > (that.value); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.copy< ast::stmt_call::ptr > (that.value); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.copy< ast::stmt_case::ptr > (that.value); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.copy< ast::stmt_continue::ptr > (that.value); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.copy< ast::stmt_default::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.copy< ast::stmt_dev::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.copy< ast::stmt_dowhile::ptr > (that.value); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.copy< ast::stmt_endon::ptr > (that.value); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.copy< ast::stmt_expr::ptr > (that.value); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.copy< ast::stmt_for::ptr > (that.value); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.copy< ast::stmt_foreach::ptr > (that.value); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.copy< ast::stmt_if::ptr > (that.value); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.copy< ast::stmt_ifelse::ptr > (that.value); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.copy< ast::stmt_list::ptr > (that.value); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.copy< ast::stmt_notify::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.copy< ast::stmt_prof_begin::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.copy< ast::stmt_prof_end::ptr > (that.value); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.copy< ast::stmt_return::ptr > (that.value); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.copy< ast::stmt_switch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.copy< ast::stmt_wait::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.copy< ast::stmt_waitframe::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.copy< ast::stmt_waittill::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.copy< ast::stmt_waittillframeend::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.copy< ast::stmt_waittillmatch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.copy< ast::stmt_while::ptr > (that.value); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.copy< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (that.value); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (that.value); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (that.value); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (that.value); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (that.value); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (that.value); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (that.value); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (that.value); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (that.value); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (that.value); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (that.value); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (that.value); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (that.value); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (that.value); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (that.value); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (that.value); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (that.value); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (that.value); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (that.value); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (that.value); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (that.value); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (that.value); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (that.value); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (that.value); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (that.value); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (that.value); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (that.value); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (that.value); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (that.value); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (that.value); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (that.value); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (that.value); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (that.value); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (that.value); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (that.value); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (that.value); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (that.value); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (that.value); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (that.value); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (that.value); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (that.value); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (that.value); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (that.value); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (that.value); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (that.value); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (that.value); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (that.value); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (that.value); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (that.value); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (that.value); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (that.value); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (that.value); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (that.value); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (that.value); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (that.value); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (that.value); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (that.value); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< ast::stmt_waitframe::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (that.value); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (that.value); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (that.value); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (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 S1CDEBUG + 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) YY_NOEXCEPT + { + yystack_.pop (n); + } + +#if S1CDEBUG + 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 // S1CDEBUG + + 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) YY_NOEXCEPT + { + return yyvalue == yypact_ninf_; + } + + bool + parser::yy_table_value_is_error_ (int yyvalue) YY_NOEXCEPT + { + 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 (lexer)); + 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + yylhs.value.emplace< ast::call > (); + break; + + case symbol_kind::S_declaration: // declaration + yylhs.value.emplace< ast::decl > (); + break; + + case symbol_kind::S_decl_constant: // decl_constant + yylhs.value.emplace< ast::decl_constant::ptr > (); + break; + + case symbol_kind::S_decl_thread: // decl_thread + yylhs.value.emplace< ast::decl_thread::ptr > (); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + yylhs.value.emplace< ast::decl_usingtree::ptr > (); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + yylhs.value.emplace< ast::expr > (); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + yylhs.value.emplace< ast::expr_add_array::ptr > (); + break; + + case symbol_kind::S_expr_anim: // expr_anim + yylhs.value.emplace< ast::expr_anim::ptr > (); + break; + + case symbol_kind::S_expr_animation: // expr_animation + yylhs.value.emplace< ast::expr_animation::ptr > (); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + yylhs.value.emplace< ast::expr_animtree::ptr > (); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + yylhs.value.emplace< ast::expr_arguments::ptr > (); + break; + + case symbol_kind::S_expr_array: // expr_array + yylhs.value.emplace< ast::expr_array::ptr > (); + break; + + case symbol_kind::S_expr_call: // expr_call + yylhs.value.emplace< ast::expr_call::ptr > (); + break; + + case symbol_kind::S_expr_complement: // expr_complement + yylhs.value.emplace< ast::expr_complement::ptr > (); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + yylhs.value.emplace< ast::expr_empty_array::ptr > (); + break; + + case symbol_kind::S_expr_false: // expr_false + yylhs.value.emplace< ast::expr_false::ptr > (); + break; + + case symbol_kind::S_expr_field: // expr_field + yylhs.value.emplace< ast::expr_field::ptr > (); + break; + + case symbol_kind::S_expr_float: // expr_float + yylhs.value.emplace< ast::expr_float::ptr > (); + break; + + case symbol_kind::S_expr_game: // expr_game + yylhs.value.emplace< ast::expr_game::ptr > (); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + yylhs.value.emplace< ast::expr_identifier::ptr > (); + break; + + case symbol_kind::S_expr_integer: // expr_integer + yylhs.value.emplace< ast::expr_integer::ptr > (); + break; + + case symbol_kind::S_expr_istring: // expr_istring + yylhs.value.emplace< ast::expr_istring::ptr > (); + break; + + case symbol_kind::S_expr_level: // expr_level + yylhs.value.emplace< ast::expr_level::ptr > (); + break; + + case symbol_kind::S_expr_method: // expr_method + yylhs.value.emplace< ast::expr_method::ptr > (); + break; + + case symbol_kind::S_expr_negate: // expr_negate + yylhs.value.emplace< ast::expr_negate::ptr > (); + break; + + case symbol_kind::S_expr_not: // expr_not + yylhs.value.emplace< ast::expr_not::ptr > (); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + yylhs.value.emplace< ast::expr_parameters::ptr > (); + break; + + case symbol_kind::S_expr_paren: // expr_paren + yylhs.value.emplace< ast::expr_paren::ptr > (); + break; + + case symbol_kind::S_expr_path: // expr_path + yylhs.value.emplace< ast::expr_path::ptr > (); + break; + + case symbol_kind::S_expr_reference: // expr_reference + yylhs.value.emplace< ast::expr_reference::ptr > (); + break; + + case symbol_kind::S_expr_self: // expr_self + yylhs.value.emplace< ast::expr_self::ptr > (); + break; + + case symbol_kind::S_expr_size: // expr_size + yylhs.value.emplace< ast::expr_size::ptr > (); + break; + + case symbol_kind::S_expr_string: // expr_string + yylhs.value.emplace< ast::expr_string::ptr > (); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + yylhs.value.emplace< ast::expr_thisthread::ptr > (); + break; + + case symbol_kind::S_expr_true: // expr_true + yylhs.value.emplace< ast::expr_true::ptr > (); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + yylhs.value.emplace< ast::expr_tuple::ptr > (); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + yylhs.value.emplace< ast::expr_undefined::ptr > (); + break; + + case symbol_kind::S_expr_vector: // expr_vector + yylhs.value.emplace< ast::expr_vector::ptr > (); + break; + + case symbol_kind::S_include: // include + yylhs.value.emplace< ast::include::ptr > (); + break; + + case symbol_kind::S_program: // program + yylhs.value.emplace< ast::program::ptr > (); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + yylhs.value.emplace< ast::stmt > (); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + yylhs.value.emplace< ast::stmt_assign::ptr > (); + break; + + case symbol_kind::S_stmt_break: // stmt_break + yylhs.value.emplace< ast::stmt_break::ptr > (); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + yylhs.value.emplace< ast::stmt_breakpoint::ptr > (); + break; + + case symbol_kind::S_stmt_call: // stmt_call + yylhs.value.emplace< ast::stmt_call::ptr > (); + break; + + case symbol_kind::S_stmt_case: // stmt_case + yylhs.value.emplace< ast::stmt_case::ptr > (); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + yylhs.value.emplace< ast::stmt_continue::ptr > (); + break; + + case symbol_kind::S_stmt_default: // stmt_default + yylhs.value.emplace< ast::stmt_default::ptr > (); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + yylhs.value.emplace< ast::stmt_dev::ptr > (); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + yylhs.value.emplace< ast::stmt_dowhile::ptr > (); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + yylhs.value.emplace< ast::stmt_endon::ptr > (); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + yylhs.value.emplace< ast::stmt_expr::ptr > (); + break; + + case symbol_kind::S_stmt_for: // stmt_for + yylhs.value.emplace< ast::stmt_for::ptr > (); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + yylhs.value.emplace< ast::stmt_foreach::ptr > (); + break; + + case symbol_kind::S_stmt_if: // stmt_if + yylhs.value.emplace< ast::stmt_if::ptr > (); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + yylhs.value.emplace< ast::stmt_ifelse::ptr > (); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + yylhs.value.emplace< ast::stmt_list::ptr > (); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + yylhs.value.emplace< ast::stmt_notify::ptr > (); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + yylhs.value.emplace< ast::stmt_prof_begin::ptr > (); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + yylhs.value.emplace< ast::stmt_prof_end::ptr > (); + break; + + case symbol_kind::S_stmt_return: // stmt_return + yylhs.value.emplace< ast::stmt_return::ptr > (); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + yylhs.value.emplace< ast::stmt_switch::ptr > (); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + yylhs.value.emplace< ast::stmt_wait::ptr > (); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + yylhs.value.emplace< ast::stmt_waitframe::ptr > (); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + yylhs.value.emplace< ast::stmt_waittill::ptr > (); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + yylhs.value.emplace< ast::stmt_waittillframeend::ptr > (); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + yylhs.value.emplace< ast::stmt_waittillmatch::ptr > (); + break; + + case symbol_kind::S_stmt_while: // stmt_while + yylhs.value.emplace< ast::stmt_while::ptr > (); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + yylhs.value.emplace< std::string > (); + 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 263 "parser.ypp" + { ast = std::move(yystack_[0].value.as < ast::program::ptr > ()); } +#line 2040 "parser.cpp" + break; + + case 3: // root: %empty +#line 264 "parser.ypp" + { ast = std::make_unique(yylhs.location); } +#line 2046 "parser.cpp" + break; + + case 4: // program: program inline +#line 269 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::move(yystack_[1].value.as < ast::program::ptr > ()); } +#line 2052 "parser.cpp" + break; + + case 5: // program: program include +#line 271 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::move(yystack_[1].value.as < ast::program::ptr > ()); yylhs.value.as < ast::program::ptr > ()->includes.push_back(std::move(yystack_[0].value.as < ast::include::ptr > ())); } +#line 2058 "parser.cpp" + break; + + case 6: // program: program declaration +#line 273 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::move(yystack_[1].value.as < ast::program::ptr > ()); yylhs.value.as < ast::program::ptr > ()->declarations.push_back(std::move(yystack_[0].value.as < ast::decl > ())); } +#line 2064 "parser.cpp" + break; + + case 7: // program: inline +#line 275 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::make_unique(yylhs.location); } +#line 2070 "parser.cpp" + break; + + case 8: // program: include +#line 277 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::program::ptr > ()->includes.push_back(std::move(yystack_[0].value.as < ast::include::ptr > ())); } +#line 2076 "parser.cpp" + break; + + case 9: // program: declaration +#line 279 "parser.ypp" + { yylhs.value.as < ast::program::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::program::ptr > ()->declarations.push_back(std::move(yystack_[0].value.as < ast::decl > ())); } +#line 2082 "parser.cpp" + break; + + case 10: // inline: "#inline" expr_path ";" +#line 283 "parser.ypp" + { lexer.push_header(yystack_[1].value.as < ast::expr_path::ptr > ()->value); } +#line 2088 "parser.cpp" + break; + + case 11: // include: "#include" expr_path ";" +#line 288 "parser.ypp" + { yylhs.value.as < ast::include::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr_path::ptr > ())); } +#line 2094 "parser.cpp" + break; + + case 12: // declaration: "/#" +#line 292 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_dev_begin = std::make_unique(yylhs.location); } +#line 2100 "parser.cpp" + break; + + case 13: // declaration: "#/" +#line 293 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_dev_end = std::make_unique(yylhs.location); } +#line 2106 "parser.cpp" + break; + + case 14: // declaration: decl_usingtree +#line 294 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_usingtree = std::move(yystack_[0].value.as < ast::decl_usingtree::ptr > ()); } +#line 2112 "parser.cpp" + break; + + case 15: // declaration: decl_constant +#line 295 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_constant = std::move(yystack_[0].value.as < ast::decl_constant::ptr > ()); } +#line 2118 "parser.cpp" + break; + + case 16: // declaration: decl_thread +#line 296 "parser.ypp" + { yylhs.value.as < ast::decl > ().as_thread = std::move(yystack_[0].value.as < ast::decl_thread::ptr > ()); } +#line 2124 "parser.cpp" + break; + + case 17: // decl_usingtree: "#using_animtree" "(" expr_string ")" ";" +#line 301 "parser.ypp" + { lexer.ban_header(yylhs.location); yylhs.value.as < ast::decl_usingtree::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_string::ptr > ())); } +#line 2130 "parser.cpp" + break; + + case 18: // decl_constant: expr_identifier "=" expr ";" +#line 306 "parser.ypp" + { yylhs.value.as < ast::decl_constant::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2136 "parser.cpp" + break; + + case 19: // decl_thread: expr_identifier "(" expr_parameters ")" stmt_block +#line 311 "parser.ypp" + { lexer.ban_header(yylhs.location); yylhs.value.as < ast::decl_thread::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[2].value.as < ast::expr_parameters::ptr > ()), std::move(yystack_[0].value.as < ast::stmt_list::ptr > ())); } +#line 2142 "parser.cpp" + break; + + case 20: // stmt: stmt_block +#line 315 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_list = std::move(yystack_[0].value.as < ast::stmt_list::ptr > ()); } +#line 2148 "parser.cpp" + break; + + case 21: // stmt: stmt_call +#line 316 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_call = std::move(yystack_[0].value.as < ast::stmt_call::ptr > ()); } +#line 2154 "parser.cpp" + break; + + case 22: // stmt: stmt_assign +#line 317 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_assign = std::move(yystack_[0].value.as < ast::stmt_assign::ptr > ()); } +#line 2160 "parser.cpp" + break; + + case 23: // stmt: stmt_endon +#line 318 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_endon = std::move(yystack_[0].value.as < ast::stmt_endon::ptr > ()); } +#line 2166 "parser.cpp" + break; + + case 24: // stmt: stmt_notify +#line 319 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_notify = std::move(yystack_[0].value.as < ast::stmt_notify::ptr > ()); } +#line 2172 "parser.cpp" + break; + + case 25: // stmt: stmt_wait +#line 320 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_wait = std::move(yystack_[0].value.as < ast::stmt_wait::ptr > ()); } +#line 2178 "parser.cpp" + break; + + case 26: // stmt: stmt_waittill +#line 321 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_waittill = std::move(yystack_[0].value.as < ast::stmt_waittill::ptr > ()); } +#line 2184 "parser.cpp" + break; + + case 27: // stmt: stmt_waittillmatch +#line 322 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_waittillmatch = std::move(yystack_[0].value.as < ast::stmt_waittillmatch::ptr > ()); } +#line 2190 "parser.cpp" + break; + + case 28: // stmt: stmt_waittillframeend +#line 323 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_waittillframeend = std::move(yystack_[0].value.as < ast::stmt_waittillframeend::ptr > ()); } +#line 2196 "parser.cpp" + break; + + case 29: // stmt: stmt_waitframe +#line 324 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_waitframe = std::move(yystack_[0].value.as < ast::stmt_waitframe::ptr > ()); } +#line 2202 "parser.cpp" + break; + + case 30: // stmt: stmt_if +#line 325 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_if = std::move(yystack_[0].value.as < ast::stmt_if::ptr > ()); } +#line 2208 "parser.cpp" + break; + + case 31: // stmt: stmt_ifelse +#line 326 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_ifelse = std::move(yystack_[0].value.as < ast::stmt_ifelse::ptr > ()); } +#line 2214 "parser.cpp" + break; + + case 32: // stmt: stmt_while +#line 327 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_while = std::move(yystack_[0].value.as < ast::stmt_while::ptr > ()); } +#line 2220 "parser.cpp" + break; + + case 33: // stmt: stmt_dowhile +#line 328 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_dowhile = std::move(yystack_[0].value.as < ast::stmt_dowhile::ptr > ()); } +#line 2226 "parser.cpp" + break; + + case 34: // stmt: stmt_for +#line 329 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_for = std::move(yystack_[0].value.as < ast::stmt_for::ptr > ()); } +#line 2232 "parser.cpp" + break; + + case 35: // stmt: stmt_foreach +#line 330 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_foreach = std::move(yystack_[0].value.as < ast::stmt_foreach::ptr > ()); } +#line 2238 "parser.cpp" + break; + + case 36: // stmt: stmt_switch +#line 331 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_switch = std::move(yystack_[0].value.as < ast::stmt_switch::ptr > ()); } +#line 2244 "parser.cpp" + break; + + case 37: // stmt: stmt_case +#line 332 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_case = std::move(yystack_[0].value.as < ast::stmt_case::ptr > ()); } +#line 2250 "parser.cpp" + break; + + case 38: // stmt: stmt_default +#line 333 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_default = std::move(yystack_[0].value.as < ast::stmt_default::ptr > ()); } +#line 2256 "parser.cpp" + break; + + case 39: // stmt: stmt_break +#line 334 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_break = std::move(yystack_[0].value.as < ast::stmt_break::ptr > ()); } +#line 2262 "parser.cpp" + break; + + case 40: // stmt: stmt_continue +#line 335 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_continue = std::move(yystack_[0].value.as < ast::stmt_continue::ptr > ()); } +#line 2268 "parser.cpp" + break; + + case 41: // stmt: stmt_return +#line 336 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_return = std::move(yystack_[0].value.as < ast::stmt_return::ptr > ()); } +#line 2274 "parser.cpp" + break; + + case 42: // stmt: stmt_breakpoint +#line 337 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_breakpoint = std::move(yystack_[0].value.as < ast::stmt_breakpoint::ptr > ()); } +#line 2280 "parser.cpp" + break; + + case 43: // stmt: stmt_prof_begin +#line 338 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_prof_begin = std::move(yystack_[0].value.as < ast::stmt_prof_begin::ptr > ()); } +#line 2286 "parser.cpp" + break; + + case 44: // stmt: stmt_prof_end +#line 339 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_prof_end = std::move(yystack_[0].value.as < ast::stmt_prof_end::ptr > ()); } +#line 2292 "parser.cpp" + break; + + case 45: // stmt_or_dev: stmt +#line 343 "parser.ypp" + { yylhs.value.as < ast::stmt > () = std::move(yystack_[0].value.as < ast::stmt > ()); } +#line 2298 "parser.cpp" + break; + + case 46: // stmt_or_dev: stmt_dev +#line 344 "parser.ypp" + { yylhs.value.as < ast::stmt > ().as_dev = std::move(yystack_[0].value.as < ast::stmt_dev::ptr > ()); } +#line 2304 "parser.cpp" + break; + + case 47: // stmt_list: stmt_list stmt +#line 349 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::move(yystack_[1].value.as < ast::stmt_list::ptr > ()); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2310 "parser.cpp" + break; + + case 48: // stmt_list: stmt +#line 351 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2316 "parser.cpp" + break; + + case 49: // stmt_or_dev_list: stmt_or_dev_list stmt_or_dev +#line 356 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::move(yystack_[1].value.as < ast::stmt_list::ptr > ()); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2322 "parser.cpp" + break; + + case 50: // stmt_or_dev_list: stmt_or_dev +#line 358 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::stmt_list::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2328 "parser.cpp" + break; + + case 51: // stmt_dev: "/#" stmt_list "#/" +#line 362 "parser.ypp" + { yylhs.value.as < ast::stmt_dev::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::stmt_list::ptr > ())); } +#line 2334 "parser.cpp" + break; + + case 52: // stmt_dev: "/#" "#/" +#line 363 "parser.ypp" + { yylhs.value.as < ast::stmt_dev::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2340 "parser.cpp" + break; + + case 53: // stmt_block: "{" stmt_or_dev_list "}" +#line 367 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::move(yystack_[1].value.as < ast::stmt_list::ptr > ()); } +#line 2346 "parser.cpp" + break; + + case 54: // stmt_block: "{" "}" +#line 368 "parser.ypp" + { yylhs.value.as < ast::stmt_list::ptr > () = std::make_unique(yylhs.location); } +#line 2352 "parser.cpp" + break; + + case 55: // stmt_expr: expr_assign +#line 373 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2358 "parser.cpp" + break; + + case 56: // stmt_expr: expr_increment +#line 375 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2364 "parser.cpp" + break; + + case 57: // stmt_expr: expr_decrement +#line 377 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2370 "parser.cpp" + break; + + case 58: // stmt_expr: %empty +#line 379 "parser.ypp" + { yylhs.value.as < ast::stmt_expr::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2376 "parser.cpp" + break; + + case 59: // stmt_call: expr_call ";" +#line 384 "parser.ypp" + { yylhs.value.as < ast::stmt_call::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_call::ptr > ()))); } +#line 2382 "parser.cpp" + break; + + case 60: // stmt_call: expr_method ";" +#line 386 "parser.ypp" + { yylhs.value.as < ast::stmt_call::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_method::ptr > ()))); } +#line 2388 "parser.cpp" + break; + + case 61: // stmt_assign: expr_assign ";" +#line 391 "parser.ypp" + { yylhs.value.as < ast::stmt_assign::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2394 "parser.cpp" + break; + + case 62: // stmt_assign: expr_increment ";" +#line 393 "parser.ypp" + { yylhs.value.as < ast::stmt_assign::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2400 "parser.cpp" + break; + + case 63: // stmt_assign: expr_decrement ";" +#line 395 "parser.ypp" + { yylhs.value.as < ast::stmt_assign::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2406 "parser.cpp" + break; + + case 64: // stmt_endon: expr_object "endon" "(" expr ")" ";" +#line 400 "parser.ypp" + { yylhs.value.as < ast::stmt_endon::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ())); } +#line 2412 "parser.cpp" + break; + + case 65: // stmt_notify: expr_object "notify" "(" expr "," expr_arguments_no_empty ")" ";" +#line 405 "parser.ypp" + { yylhs.value.as < ast::stmt_notify::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < ast::expr > ()), std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2418 "parser.cpp" + break; + + case 66: // stmt_notify: expr_object "notify" "(" expr ")" ";" +#line 407 "parser.ypp" + { yylhs.value.as < ast::stmt_notify::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::make_unique(yylhs.location)); } +#line 2424 "parser.cpp" + break; + + case 67: // stmt_wait: "wait" expr ";" +#line 412 "parser.ypp" + { yylhs.value.as < ast::stmt_wait::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2430 "parser.cpp" + break; + + case 68: // stmt_waittill: expr_object "waittill" "(" expr "," expr_arguments_no_empty ")" ";" +#line 417 "parser.ypp" + { yylhs.value.as < ast::stmt_waittill::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < ast::expr > ()), std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2436 "parser.cpp" + break; + + case 69: // stmt_waittill: expr_object "waittill" "(" expr ")" ";" +#line 419 "parser.ypp" + { yylhs.value.as < ast::stmt_waittill::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::make_unique(yylhs.location)); } +#line 2442 "parser.cpp" + break; + + case 70: // stmt_waittillmatch: expr_object "waittillmatch" "(" expr "," expr_arguments_no_empty ")" ";" +#line 424 "parser.ypp" + { yylhs.value.as < ast::stmt_waittillmatch::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[7].value.as < ast::expr > ()), std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2448 "parser.cpp" + break; + + case 71: // stmt_waittillmatch: expr_object "waittillmatch" "(" expr ")" ";" +#line 426 "parser.ypp" + { yylhs.value.as < ast::stmt_waittillmatch::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::make_unique(yylhs.location)); } +#line 2454 "parser.cpp" + break; + + case 72: // stmt_waittillframeend: "waittillframeend" ";" +#line 431 "parser.ypp" + { yylhs.value.as < ast::stmt_waittillframeend::ptr > () = std::make_unique(yylhs.location); } +#line 2460 "parser.cpp" + break; + + case 73: // stmt_waitframe: "waitframe" ";" +#line 436 "parser.ypp" + { yylhs.value.as < ast::stmt_waitframe::ptr > () = std::make_unique(yylhs.location); } +#line 2466 "parser.cpp" + break; + + case 74: // stmt_waitframe: "waitframe" "(" ")" ";" +#line 438 "parser.ypp" + { yylhs.value.as < ast::stmt_waitframe::ptr > () = std::make_unique(yylhs.location); } +#line 2472 "parser.cpp" + break; + + case 75: // stmt_if: "if" "(" expr ")" stmt +#line 443 "parser.ypp" + { yylhs.value.as < ast::stmt_if::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2478 "parser.cpp" + break; + + case 76: // stmt_ifelse: "if" "(" expr ")" stmt "else" stmt +#line 448 "parser.ypp" + { yylhs.value.as < ast::stmt_ifelse::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::stmt > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2484 "parser.cpp" + break; + + case 77: // stmt_while: "while" "(" expr ")" stmt +#line 453 "parser.ypp" + { yylhs.value.as < ast::stmt_while::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2490 "parser.cpp" + break; + + case 78: // stmt_dowhile: "do" stmt "while" "(" expr ")" ";" +#line 458 "parser.ypp" + { yylhs.value.as < ast::stmt_dowhile::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[5].value.as < ast::stmt > ())); } +#line 2496 "parser.cpp" + break; + + case 79: // stmt_for: "for" "(" stmt_expr ";" expr_or_empty ";" stmt_expr ")" stmt +#line 463 "parser.ypp" + { yylhs.value.as < ast::stmt_for::ptr > () = std::make_unique(yylhs.location, ast::stmt(std::move(yystack_[6].value.as < ast::stmt_expr::ptr > ())), std::move(yystack_[4].value.as < ast::expr > ()), ast::stmt(std::move(yystack_[2].value.as < ast::stmt_expr::ptr > ())), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2502 "parser.cpp" + break; + + case 80: // stmt_foreach: "foreach" "(" expr_identifier "in" expr ")" stmt +#line 468 "parser.ypp" + { yylhs.value.as < ast::stmt_foreach::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[4].value.as < ast::expr_identifier::ptr > ())), std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2508 "parser.cpp" + break; + + case 81: // stmt_foreach: "foreach" "(" expr_identifier "," expr_identifier "in" expr ")" stmt +#line 470 "parser.ypp" + { yylhs.value.as < ast::stmt_foreach::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[6].value.as < ast::expr_identifier::ptr > ())), ast::expr(std::move(yystack_[4].value.as < ast::expr_identifier::ptr > ())), std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt > ())); } +#line 2514 "parser.cpp" + break; + + case 82: // stmt_switch: "switch" "(" expr ")" stmt_block +#line 475 "parser.ypp" + { yylhs.value.as < ast::stmt_switch::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::stmt_list::ptr > ())); } +#line 2520 "parser.cpp" + break; + + case 83: // stmt_case: "case" expr_integer ":" +#line 480 "parser.ypp" + { yylhs.value.as < ast::stmt_case::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_integer::ptr > ())), std::make_unique(yylhs.location)); } +#line 2526 "parser.cpp" + break; + + case 84: // stmt_case: "case" expr_string ":" +#line 482 "parser.ypp" + { yylhs.value.as < ast::stmt_case::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[1].value.as < ast::expr_string::ptr > ())), std::make_unique(yylhs.location)); } +#line 2532 "parser.cpp" + break; + + case 85: // stmt_default: "default" ":" +#line 487 "parser.ypp" + { yylhs.value.as < ast::stmt_default::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2538 "parser.cpp" + break; + + case 86: // stmt_break: "break" ";" +#line 492 "parser.ypp" + { yylhs.value.as < ast::stmt_break::ptr > () = std::make_unique(yylhs.location); } +#line 2544 "parser.cpp" + break; + + case 87: // stmt_continue: "continue" ";" +#line 497 "parser.ypp" + { yylhs.value.as < ast::stmt_continue::ptr > () = std::make_unique(yylhs.location); } +#line 2550 "parser.cpp" + break; + + case 88: // stmt_return: "return" expr ";" +#line 502 "parser.ypp" + { yylhs.value.as < ast::stmt_return::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 2556 "parser.cpp" + break; + + case 89: // stmt_return: "return" ";" +#line 504 "parser.ypp" + { yylhs.value.as < ast::stmt_return::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location)); } +#line 2562 "parser.cpp" + break; + + case 90: // stmt_breakpoint: "breakpoint" ";" +#line 509 "parser.ypp" + { yylhs.value.as < ast::stmt_breakpoint::ptr > () = std::make_unique(yylhs.location); } +#line 2568 "parser.cpp" + break; + + case 91: // stmt_prof_begin: "prof_begin" "(" expr_arguments ")" ";" +#line 514 "parser.ypp" + { yylhs.value.as < ast::stmt_prof_begin::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2574 "parser.cpp" + break; + + case 92: // stmt_prof_end: "prof_end" "(" expr_arguments ")" ";" +#line 519 "parser.ypp" + { yylhs.value.as < ast::stmt_prof_end::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ())); } +#line 2580 "parser.cpp" + break; + + case 93: // expr: expr_ternary +#line 523 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2586 "parser.cpp" + break; + + case 94: // expr: expr_binary +#line 524 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2592 "parser.cpp" + break; + + case 95: // expr: expr_primitive +#line 525 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2598 "parser.cpp" + break; + + case 96: // expr_or_empty: expr +#line 529 "parser.ypp" + { yylhs.value.as < ast::expr > () = std::move(yystack_[0].value.as < ast::expr > ()); } +#line 2604 "parser.cpp" + break; + + case 97: // expr_or_empty: %empty +#line 530 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location); } +#line 2610 "parser.cpp" + break; + + case 98: // expr_assign: expr_tuple "=" expr +#line 535 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2616 "parser.cpp" + break; + + case 99: // expr_assign: expr_object "=" expr +#line 537 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2622 "parser.cpp" + break; + + case 100: // expr_assign: expr_object "|=" expr +#line 539 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2628 "parser.cpp" + break; + + case 101: // expr_assign: expr_object "&=" expr +#line 541 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2634 "parser.cpp" + break; + + case 102: // expr_assign: expr_object "^=" expr +#line 543 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2640 "parser.cpp" + break; + + case 103: // expr_assign: expr_object "<<=" expr +#line 545 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()),std::move( yystack_[0].value.as < ast::expr > ())); } +#line 2646 "parser.cpp" + break; + + case 104: // expr_assign: expr_object ">>=" expr +#line 547 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2652 "parser.cpp" + break; + + case 105: // expr_assign: expr_object "+=" expr +#line 549 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2658 "parser.cpp" + break; + + case 106: // expr_assign: expr_object "-=" expr +#line 551 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2664 "parser.cpp" + break; + + case 107: // expr_assign: expr_object "*=" expr +#line 553 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2670 "parser.cpp" + break; + + case 108: // expr_assign: expr_object "/=" expr +#line 555 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2676 "parser.cpp" + break; + + case 109: // expr_assign: expr_object "%=" expr +#line 557 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2682 "parser.cpp" + break; + + case 110: // expr_increment: "++" expr_object +#line 562 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ()), true); } +#line 2688 "parser.cpp" + break; + + case 111: // expr_increment: expr_object "++" +#line 564 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), false); } +#line 2694 "parser.cpp" + break; + + case 112: // expr_decrement: "--" expr_object +#line 569 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ()), true); } +#line 2700 "parser.cpp" + break; + + case 113: // expr_decrement: expr_object "--" +#line 571 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), false); } +#line 2706 "parser.cpp" + break; + + case 114: // expr_ternary: expr "?" expr ":" expr +#line 576 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[4].value.as < ast::expr > ()), std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2712 "parser.cpp" + break; + + case 115: // expr_binary: expr "||" expr +#line 581 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2718 "parser.cpp" + break; + + case 116: // expr_binary: expr "&&" expr +#line 583 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2724 "parser.cpp" + break; + + case 117: // expr_binary: expr "==" expr +#line 585 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2730 "parser.cpp" + break; + + case 118: // expr_binary: expr "!=" expr +#line 587 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2736 "parser.cpp" + break; + + case 119: // expr_binary: expr "<=" expr +#line 589 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2742 "parser.cpp" + break; + + case 120: // expr_binary: expr ">=" expr +#line 591 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2748 "parser.cpp" + break; + + case 121: // expr_binary: expr "<" expr +#line 593 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2754 "parser.cpp" + break; + + case 122: // expr_binary: expr ">" expr +#line 595 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2760 "parser.cpp" + break; + + case 123: // expr_binary: expr "|" expr +#line 597 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2766 "parser.cpp" + break; + + case 124: // expr_binary: expr "&" expr +#line 599 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2772 "parser.cpp" + break; + + case 125: // expr_binary: expr "^" expr +#line 601 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2778 "parser.cpp" + break; + + case 126: // expr_binary: expr "<<" expr +#line 603 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2784 "parser.cpp" + break; + + case 127: // expr_binary: expr ">>" expr +#line 605 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2790 "parser.cpp" + break; + + case 128: // expr_binary: expr "+" expr +#line 607 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2796 "parser.cpp" + break; + + case 129: // expr_binary: expr "-" expr +#line 609 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2802 "parser.cpp" + break; + + case 130: // expr_binary: expr "*" expr +#line 611 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2808 "parser.cpp" + break; + + case 131: // expr_binary: expr "/" expr +#line 613 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2814 "parser.cpp" + break; + + case 132: // expr_binary: expr "%" expr +#line 615 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2820 "parser.cpp" + break; + + case 133: // expr_primitive: expr_complement +#line 619 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_complement::ptr > ()); } +#line 2826 "parser.cpp" + break; + + case 134: // expr_primitive: expr_negate +#line 620 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_negate::ptr > ()); } +#line 2832 "parser.cpp" + break; + + case 135: // expr_primitive: expr_not +#line 621 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_not::ptr > ()); } +#line 2838 "parser.cpp" + break; + + case 136: // expr_primitive: expr_call +#line 622 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_call::ptr > ()); } +#line 2844 "parser.cpp" + break; + + case 137: // expr_primitive: expr_method +#line 623 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_method::ptr > ()); } +#line 2850 "parser.cpp" + break; + + case 138: // expr_primitive: expr_add_array +#line 624 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_add_array::ptr > ()); } +#line 2856 "parser.cpp" + break; + + case 139: // expr_primitive: expr_reference +#line 625 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_reference::ptr > ()); } +#line 2862 "parser.cpp" + break; + + case 140: // expr_primitive: expr_array +#line 626 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_array::ptr > ()); } +#line 2868 "parser.cpp" + break; + + case 141: // expr_primitive: expr_field +#line 627 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_field::ptr > ()); } +#line 2874 "parser.cpp" + break; + + case 142: // expr_primitive: expr_size +#line 628 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_size::ptr > ()); } +#line 2880 "parser.cpp" + break; + + case 143: // expr_primitive: expr_paren +#line 629 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_paren::ptr > ()); } +#line 2886 "parser.cpp" + break; + + case 144: // expr_primitive: expr_thisthread +#line 630 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_thisthread::ptr > ()); } +#line 2892 "parser.cpp" + break; + + case 145: // expr_primitive: expr_empty_array +#line 631 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_empty_array::ptr > ()); } +#line 2898 "parser.cpp" + break; + + case 146: // expr_primitive: expr_undefined +#line 632 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_undefined::ptr > ()); } +#line 2904 "parser.cpp" + break; + + case 147: // expr_primitive: expr_game +#line 633 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_game::ptr > ()); } +#line 2910 "parser.cpp" + break; + + case 148: // expr_primitive: expr_self +#line 634 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_self::ptr > ()); } +#line 2916 "parser.cpp" + break; + + case 149: // expr_primitive: expr_anim +#line 635 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_anim::ptr > ()); } +#line 2922 "parser.cpp" + break; + + case 150: // expr_primitive: expr_level +#line 636 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_level::ptr > ()); } +#line 2928 "parser.cpp" + break; + + case 151: // expr_primitive: expr_animation +#line 637 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_animation::ptr > ()); } +#line 2934 "parser.cpp" + break; + + case 152: // expr_primitive: expr_animtree +#line 638 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_animtree::ptr > ()); } +#line 2940 "parser.cpp" + break; + + case 153: // expr_primitive: expr_identifier +#line 639 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()); } +#line 2946 "parser.cpp" + break; + + case 154: // expr_primitive: expr_istring +#line 640 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_istring::ptr > ()); } +#line 2952 "parser.cpp" + break; + + case 155: // expr_primitive: expr_string +#line 641 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_string::ptr > ()); } +#line 2958 "parser.cpp" + break; + + case 156: // expr_primitive: expr_vector +#line 642 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_vector::ptr > ()); } +#line 2964 "parser.cpp" + break; + + case 157: // expr_primitive: expr_float +#line 643 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_float::ptr > ()); } +#line 2970 "parser.cpp" + break; + + case 158: // expr_primitive: expr_integer +#line 644 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_integer::ptr > ()); } +#line 2976 "parser.cpp" + break; + + case 159: // expr_primitive: expr_false +#line 645 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_false::ptr > ()); } +#line 2982 "parser.cpp" + break; + + case 160: // expr_primitive: expr_true +#line 646 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_true::ptr > ()); } +#line 2988 "parser.cpp" + break; + + case 161: // expr_complement: "~" expr +#line 651 "parser.ypp" + { yylhs.value.as < ast::expr_complement::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 2994 "parser.cpp" + break; + + case 162: // expr_negate: "-" expr_identifier +#line 656 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()))); } +#line 3000 "parser.cpp" + break; + + case 163: // expr_negate: "-" expr_paren +#line 658 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_paren::ptr > ()))); } +#line 3006 "parser.cpp" + break; + + case 164: // expr_negate: "-" expr_array +#line 660 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_array::ptr > ()))); } +#line 3012 "parser.cpp" + break; + + case 165: // expr_negate: "-" expr_field +#line 662 "parser.ypp" + { yylhs.value.as < ast::expr_negate::ptr > () = std::make_unique(yylhs.location, ast::expr(std::move(yystack_[0].value.as < ast::expr_field::ptr > ()))); } +#line 3018 "parser.cpp" + break; + + case 166: // expr_not: "!" expr +#line 667 "parser.ypp" + { yylhs.value.as < ast::expr_not::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3024 "parser.cpp" + break; + + case 167: // expr_call: expr_function +#line 671 "parser.ypp" + { yylhs.value.as < ast::expr_call::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::call > ())); } +#line 3030 "parser.cpp" + break; + + case 168: // expr_call: expr_pointer +#line 672 "parser.ypp" + { yylhs.value.as < ast::expr_call::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[0].value.as < ast::call > ())); } +#line 3036 "parser.cpp" + break; + + case 169: // expr_method: expr_object expr_function +#line 675 "parser.ypp" + { yylhs.value.as < ast::expr_method::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::call > ())); } +#line 3042 "parser.cpp" + break; + + case 170: // expr_method: expr_object expr_pointer +#line 676 "parser.ypp" + { yylhs.value.as < ast::expr_method::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::call > ())); } +#line 3048 "parser.cpp" + break; + + case 171: // expr_function: expr_identifier "(" expr_arguments ")" +#line 681 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::normal); } +#line 3054 "parser.cpp" + break; + + case 172: // expr_function: expr_path "::" expr_identifier "(" expr_arguments ")" +#line 683 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr_path::ptr > ()), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::normal); } +#line 3060 "parser.cpp" + break; + + case 173: // expr_function: "thread" expr_identifier "(" expr_arguments ")" +#line 685 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::thread); } +#line 3066 "parser.cpp" + break; + + case 174: // expr_function: "thread" expr_path "::" expr_identifier "(" expr_arguments ")" +#line 687 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr_path::ptr > ()), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::thread); } +#line 3072 "parser.cpp" + break; + + case 175: // expr_function: "childthread" expr_identifier "(" expr_arguments ")" +#line 689 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::childthread); } +#line 3078 "parser.cpp" + break; + + case 176: // expr_function: "childthread" expr_path "::" expr_identifier "(" expr_arguments ")" +#line 691 "parser.ypp" + { yylhs.value.as < ast::call > ().as_function = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr_path::ptr > ()), std::move(yystack_[3].value.as < ast::expr_identifier::ptr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::childthread); } +#line 3084 "parser.cpp" + break; + + case 177: // expr_pointer: "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 696 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::normal); } +#line 3090 "parser.cpp" + break; + + case 178: // expr_pointer: "thread" "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 698 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::thread); } +#line 3096 "parser.cpp" + break; + + case 179: // expr_pointer: "childthread" "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 700 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::childthread); } +#line 3102 "parser.cpp" + break; + + case 180: // expr_pointer: "call" "[" "[" expr "]" "]" "(" expr_arguments ")" +#line 702 "parser.ypp" + { yylhs.value.as < ast::call > ().as_pointer = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ()), ast::call::mode::builtin); } +#line 3108 "parser.cpp" + break; + + case 181: // expr_add_array: "[" expr_arguments_no_empty "]" +#line 707 "parser.ypp" + { yylhs.value.as < ast::expr_add_array::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr_arguments::ptr > ())); } +#line 3114 "parser.cpp" + break; + + case 182: // expr_parameters: expr_parameters "," expr_identifier +#line 712 "parser.ypp" + { yylhs.value.as < ast::expr_parameters::ptr > () = std::move(yystack_[2].value.as < ast::expr_parameters::ptr > ()); yylhs.value.as < ast::expr_parameters::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3120 "parser.cpp" + break; + + case 183: // expr_parameters: expr_identifier +#line 714 "parser.ypp" + { yylhs.value.as < ast::expr_parameters::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::expr_parameters::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3126 "parser.cpp" + break; + + case 184: // expr_parameters: %empty +#line 716 "parser.ypp" + { yylhs.value.as < ast::expr_parameters::ptr > () = std::make_unique(yylhs.location); } +#line 3132 "parser.cpp" + break; + + case 185: // expr_arguments: expr_arguments_no_empty +#line 721 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::move(yystack_[0].value.as < ast::expr_arguments::ptr > ()); } +#line 3138 "parser.cpp" + break; + + case 186: // expr_arguments: %empty +#line 723 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::make_unique(yylhs.location); } +#line 3144 "parser.cpp" + break; + + case 187: // expr_arguments_no_empty: expr_arguments "," expr +#line 728 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::move(yystack_[2].value.as < ast::expr_arguments::ptr > ()); yylhs.value.as < ast::expr_arguments::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3150 "parser.cpp" + break; + + case 188: // expr_arguments_no_empty: expr +#line 730 "parser.ypp" + { yylhs.value.as < ast::expr_arguments::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::expr_arguments::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3156 "parser.cpp" + break; + + case 189: // expr_reference: "::" expr_identifier +#line 735 "parser.ypp" + { yylhs.value.as < ast::expr_reference::ptr > () = std::make_unique(yylhs.location, std::make_unique(yylhs.location), std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3162 "parser.cpp" + break; + + case 190: // expr_reference: expr_path "::" expr_identifier +#line 737 "parser.ypp" + { yylhs.value.as < ast::expr_reference::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr_path::ptr > ()), std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3168 "parser.cpp" + break; + + case 191: // expr_tuple: "[" expr_tuple_arguments "]" +#line 742 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[1].value.as < ast::expr_tuple::ptr > ()); } +#line 3174 "parser.cpp" + break; + + case 192: // expr_tuple_arguments: expr_tuple_arguments "," expr_tuple_types +#line 747 "parser.ypp" + { yylhs.value.as < ast::expr_tuple::ptr > () = std::move(yystack_[2].value.as < ast::expr_tuple::ptr > ()); yylhs.value.as < ast::expr_tuple::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3180 "parser.cpp" + break; + + case 193: // expr_tuple_arguments: expr_tuple_types +#line 749 "parser.ypp" + { yylhs.value.as < ast::expr_tuple::ptr > () = std::make_unique(yylhs.location); yylhs.value.as < ast::expr_tuple::ptr > ()->list.push_back(std::move(yystack_[0].value.as < ast::expr > ())); } +#line 3186 "parser.cpp" + break; + + case 194: // expr_tuple_types: expr_array +#line 753 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_array::ptr > ()); } +#line 3192 "parser.cpp" + break; + + case 195: // expr_tuple_types: expr_field +#line 754 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_field::ptr > ()); } +#line 3198 "parser.cpp" + break; + + case 196: // expr_tuple_types: expr_identifier +#line 755 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()); } +#line 3204 "parser.cpp" + break; + + case 197: // expr_array: expr_object "[" expr "]" +#line 760 "parser.ypp" + { yylhs.value.as < ast::expr_array::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[3].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr > ())); } +#line 3210 "parser.cpp" + break; + + case 198: // expr_field: expr_object "." expr_identifier_nosize +#line 765 "parser.ypp" + { yylhs.value.as < ast::expr_field::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ()), std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ())); } +#line 3216 "parser.cpp" + break; + + case 199: // expr_size: expr_object "." "size" +#line 770 "parser.ypp" + { yylhs.value.as < ast::expr_size::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[2].value.as < ast::expr > ())); } +#line 3222 "parser.cpp" + break; + + case 200: // expr_paren: "(" expr ")" +#line 775 "parser.ypp" + { yylhs.value.as < ast::expr_paren::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[1].value.as < ast::expr > ())); } +#line 3228 "parser.cpp" + break; + + case 201: // expr_object: expr_call +#line 779 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_call::ptr > ()); } +#line 3234 "parser.cpp" + break; + + case 202: // expr_object: expr_method +#line 780 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_method::ptr > ()); } +#line 3240 "parser.cpp" + break; + + case 203: // expr_object: expr_array +#line 781 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_array::ptr > ()); } +#line 3246 "parser.cpp" + break; + + case 204: // expr_object: expr_field +#line 782 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_field::ptr > ()); } +#line 3252 "parser.cpp" + break; + + case 205: // expr_object: expr_game +#line 783 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_game::ptr > ()); } +#line 3258 "parser.cpp" + break; + + case 206: // expr_object: expr_self +#line 784 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_self::ptr > ()); } +#line 3264 "parser.cpp" + break; + + case 207: // expr_object: expr_anim +#line 785 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_anim::ptr > ()); } +#line 3270 "parser.cpp" + break; + + case 208: // expr_object: expr_level +#line 786 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_level::ptr > ()); } +#line 3276 "parser.cpp" + break; + + case 209: // expr_object: expr_identifier +#line 787 "parser.ypp" + { yylhs.value.as < ast::expr > ().as_node = std::move(yystack_[0].value.as < ast::expr_identifier::ptr > ()); } +#line 3282 "parser.cpp" + break; + + case 210: // expr_thisthread: "thisthread" +#line 792 "parser.ypp" + { yylhs.value.as < ast::expr_thisthread::ptr > () = std::make_unique(yylhs.location); } +#line 3288 "parser.cpp" + break; + + case 211: // expr_empty_array: "[" "]" +#line 797 "parser.ypp" + { yylhs.value.as < ast::expr_empty_array::ptr > () = std::make_unique(yylhs.location); } +#line 3294 "parser.cpp" + break; + + case 212: // expr_undefined: "undefined" +#line 802 "parser.ypp" + { yylhs.value.as < ast::expr_undefined::ptr > () = std::make_unique(yylhs.location); } +#line 3300 "parser.cpp" + break; + + case 213: // expr_game: "game" +#line 807 "parser.ypp" + { yylhs.value.as < ast::expr_game::ptr > () = std::make_unique(yylhs.location); } +#line 3306 "parser.cpp" + break; + + case 214: // expr_self: "self" +#line 812 "parser.ypp" + { yylhs.value.as < ast::expr_self::ptr > () = std::make_unique(yylhs.location); } +#line 3312 "parser.cpp" + break; + + case 215: // expr_anim: "anim" +#line 817 "parser.ypp" + { yylhs.value.as < ast::expr_anim::ptr > () = std::make_unique(yylhs.location); } +#line 3318 "parser.cpp" + break; + + case 216: // expr_level: "level" +#line 822 "parser.ypp" + { yylhs.value.as < ast::expr_level::ptr > () = std::make_unique(yylhs.location); } +#line 3324 "parser.cpp" + break; + + case 217: // expr_animation: "%" "identifier" +#line 827 "parser.ypp" + { yylhs.value.as < ast::expr_animation::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3330 "parser.cpp" + break; + + case 218: // expr_animtree: "#animtree" +#line 832 "parser.ypp" + { yylhs.value.as < ast::expr_animtree::ptr > () = std::make_unique(yylhs.location); } +#line 3336 "parser.cpp" + break; + + case 219: // expr_identifier_nosize: "identifier" +#line 837 "parser.ypp" + { yylhs.value.as < ast::expr_identifier::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3342 "parser.cpp" + break; + + case 220: // expr_identifier: "identifier" +#line 842 "parser.ypp" + { yylhs.value.as < ast::expr_identifier::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3348 "parser.cpp" + break; + + case 221: // expr_identifier: "size" +#line 844 "parser.ypp" + { yylhs.value.as < ast::expr_identifier::ptr > () = std::make_unique(yylhs.location, "size"); } +#line 3354 "parser.cpp" + break; + + case 222: // expr_path: "identifier" +#line 849 "parser.ypp" + { yylhs.value.as < ast::expr_path::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3360 "parser.cpp" + break; + + case 223: // expr_path: "path" +#line 851 "parser.ypp" + { yylhs.value.as < ast::expr_path::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3366 "parser.cpp" + break; + + case 224: // expr_istring: "localized string" +#line 856 "parser.ypp" + { yylhs.value.as < ast::expr_istring::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3372 "parser.cpp" + break; + + case 225: // expr_string: "string literal" +#line 861 "parser.ypp" + { yylhs.value.as < ast::expr_string::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3378 "parser.cpp" + break; + + case 226: // expr_vector: "(" expr "," expr "," expr ")" +#line 866 "parser.ypp" + { yylhs.value.as < ast::expr_vector::ptr > () = std::make_unique(yylhs.location, std::move(yystack_[5].value.as < ast::expr > ()), std::move(yystack_[3].value.as < ast::expr > ()), std::move(yystack_[1].value.as < ast::expr > ())); } +#line 3384 "parser.cpp" + break; + + case 227: // expr_float: "-" "float" +#line 871 "parser.ypp" + { yylhs.value.as < ast::expr_float::ptr > () = std::make_unique(yylhs.location, "-" + yystack_[0].value.as < std::string > ()); } +#line 3390 "parser.cpp" + break; + + case 228: // expr_float: "float" +#line 873 "parser.ypp" + { yylhs.value.as < ast::expr_float::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3396 "parser.cpp" + break; + + case 229: // expr_integer: "-" "integer" +#line 878 "parser.ypp" + { yylhs.value.as < ast::expr_integer::ptr > () = std::make_unique(yylhs.location, "-" + yystack_[0].value.as < std::string > ()); } +#line 3402 "parser.cpp" + break; + + case 230: // expr_integer: "integer" +#line 880 "parser.ypp" + { yylhs.value.as < ast::expr_integer::ptr > () = std::make_unique(yylhs.location, yystack_[0].value.as < std::string > ()); } +#line 3408 "parser.cpp" + break; + + case 231: // expr_false: "false" +#line 885 "parser.ypp" + { yylhs.value.as < ast::expr_false::ptr > () = std::make_unique(yylhs.location); } +#line 3414 "parser.cpp" + break; + + case 232: // expr_true: "true" +#line 890 "parser.ypp" + { yylhs.value.as < ast::expr_true::ptr > () = std::make_unique(yylhs.location); } +#line 3420 "parser.cpp" + break; + + +#line 3424 "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", "#define", "#undef", "#ifdef", + "#ifndef", "#if", "#elif", "#else", "#endif", "/#", "#/", "#inline", + "#include", "#using_animtree", "#animtree", "endon", "notify", "wait", + "waittill", "waittillmatch", "waittillframeend", "waitframe", "if", + "else", "do", "while", "for", "foreach", "in", "switch", "case", + "default", "break", "continue", "return", "breakpoint", "prof_begin", + "prof_end", "thread", "childthread", "thisthread", "call", "true", + "false", "undefined", "size", "game", "self", "anim", "level", "(", ")", + "{", "}", "[", "]", ",", ".", "::", ":", ";", "?", "++", "--", "<<", + ">>", "||", "&&", "==", "!=", "<=", ">=", "<", ">", "!", "~", "=", "+=", + "-=", "*=", "/=", "%=", "|=", "&=", "^=", ">>=", "<<=", "|", "&", "^", + "+", "-", "*", "/", "%", "path", "identifier", "string literal", + "localized string", "float", "integer", "SIZEOF", "ADD_ARRAY", "THEN", + "TERN", "NEG", "ANIMREF", "PREINC", "PREDEC", "POSTINC", "POSTDEC", + "$accept", "root", "program", "inline", "include", "declaration", + "decl_usingtree", "decl_constant", "decl_thread", "stmt", "stmt_or_dev", + "stmt_list", "stmt_or_dev_list", "stmt_dev", "stmt_block", "stmt_expr", + "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_dowhile", + "stmt_for", "stmt_foreach", "stmt_switch", "stmt_case", "stmt_default", + "stmt_break", "stmt_continue", "stmt_return", "stmt_breakpoint", + "stmt_prof_begin", "stmt_prof_end", "expr", "expr_or_empty", + "expr_assign", "expr_increment", "expr_decrement", "expr_ternary", + "expr_binary", "expr_primitive", "expr_complement", "expr_negate", + "expr_not", "expr_call", "expr_method", "expr_function", "expr_pointer", + "expr_add_array", "expr_parameters", "expr_arguments", + "expr_arguments_no_empty", "expr_reference", "expr_tuple", + "expr_tuple_arguments", "expr_tuple_types", "expr_array", "expr_field", + "expr_size", "expr_paren", "expr_object", "expr_thisthread", + "expr_empty_array", "expr_undefined", "expr_game", "expr_self", + "expr_anim", "expr_level", "expr_animation", "expr_animtree", + "expr_identifier_nosize", "expr_identifier", "expr_path", "expr_istring", + "expr_string", "expr_vector", "expr_float", "expr_integer", "expr_false", + "expr_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 S1CDEBUG + // 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 S1CDEBUG + 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_) + return true; + else + { +#if S1CDEBUG + YYCDEBUG << "LAC: initial context established for " + << symbol_name (yytoken) << '\n'; +#endif + yy_lac_established_ = true; + return yy_lac_check_ (yytoken); + } + } + + // Discard any previous initial lookahead context. + void + parser::yy_lac_discard_ (const char* event) + { + /* 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 " + << event << '\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_ = -287; + + const short parser::yytable_ninf_ = -223; + + const short + parser::yypact_[] = + { + 6, -287, -287, 5, 5, -24, -287, -287, 37, 6, + -287, -287, -287, -287, -287, -287, -8, -287, -287, -13, + -10, -54, -287, -287, -287, -287, -23, 1223, -287, -287, + -287, 11, -12, -287, -287, -42, 3, -287, 17, -287, + -287, -287, -287, -287, -287, -287, 1223, 821, -23, 1223, + 1223, -18, -36, 26, -287, -287, -287, 2187, -287, -287, + -287, -287, -287, -287, 413, 667, -287, -287, -287, -287, + 699, 729, -287, -287, 1012, -287, -287, -287, 1089, 1187, + 1247, 1317, -287, -287, 574, 39, -287, -287, -287, -287, + -287, -287, -287, 15, 96, -23, 49, 75, 81, 114, + 100, 124, 129, 1439, 821, -287, 2270, 134, 136, -287, + -287, -287, 1223, 142, -287, -287, -287, -287, 699, 729, + -287, 1406, -287, -287, -287, -287, 574, 140, -287, -287, + 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, + 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1286, + -20, -287, -287, 152, 1223, -23, -287, 928, -287, -287, + 1223, 1223, -23, 1223, 1223, -23, 1223, -287, 1223, 1917, + 1223, -287, 1605, 1223, 107, -23, 2152, 179, 179, 2301, + 2311, 2383, 2383, 30, 30, 30, 30, 2342, 728, 2352, + 73, 73, -287, -287, -287, 1957, -287, -287, -287, 35, + -287, 154, 1057, 1223, 146, -5, 161, 1370, 165, 166, + 167, 168, -17, 163, 169, 172, 1160, 183, 173, 175, + -287, 139, 548, 548, -287, -287, 980, -287, -287, -287, + -287, -287, -287, -287, -287, -287, -287, -287, -287, -287, + -287, -287, -287, -287, -287, -287, -287, -287, -287, -287, + -287, -287, -287, 184, 185, 188, 191, 192, 177, -287, + -287, 51, 152, 1997, 53, 205, 2037, 56, 206, 2077, + 2116, 203, 2270, 1917, 154, 1223, -287, -287, 1223, -287, + -287, 1134, 2222, -287, 209, -287, 1223, 236, 1223, 639, + -23, 1223, 164, 208, 215, -287, -287, -287, -287, 2257, + -287, 1223, 1223, 1286, 32, -287, 62, 86, 8, 1406, + 1406, -287, -287, -287, -287, -287, -287, -287, 1223, 225, + 227, 228, 230, -287, -287, 1223, 1223, 1223, 1223, 1223, + 1223, 1223, 1223, 1223, 1223, 1223, 210, -287, 1223, 226, + -287, 1223, 229, 1223, 232, 2270, 59, -287, -287, -287, + 223, 1639, 235, 1673, 233, -287, -287, -287, 1396, 9, + 1707, -287, -287, -287, 60, 87, -287, 548, 2270, 1223, + 1223, 1223, 1223, 2270, 2270, 2270, 2270, 2270, 2270, 2270, + 2270, 2270, 2270, 2270, 240, 89, 242, 101, 245, 1741, + 1223, -287, -287, 1370, 1223, 1370, 1223, 1223, -23, 96, + 237, 241, -287, 1775, 1483, 1527, 1571, 1223, -287, 1223, + -287, 1223, -287, 103, 273, 1809, -287, 2270, 243, 1843, + 272, -287, -287, -287, 246, 249, 1223, 250, 1223, 251, + 1223, 113, 123, 125, -287, 1370, 252, 639, 1370, 1223, + -287, -287, 254, -287, 262, -287, 286, -287, -287, -287, + -287, -287, 287, -287, 1877, 279, 280, 281, 1370, 1370, + -287, -287, -287, -287, -287 + }; + + const unsigned char + parser::yydefact_[] = + { + 3, 12, 13, 0, 0, 0, 221, 220, 0, 2, + 7, 8, 9, 14, 15, 16, 0, 223, 222, 0, + 0, 0, 1, 4, 5, 6, 184, 0, 10, 11, + 225, 0, 0, 183, 218, 0, 0, 210, 0, 232, + 231, 212, 213, 214, 215, 216, 0, 186, 0, 0, + 0, 0, 0, 220, 224, 228, 230, 0, 93, 94, + 95, 133, 134, 135, 136, 137, 167, 168, 138, 139, + 140, 141, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 0, 154, 155, 156, 157, + 158, 159, 160, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 186, 211, 188, 0, 185, 189, + 166, 161, 0, 0, 227, 229, 201, 202, 164, 165, + 163, 0, 205, 206, 207, 208, 162, 0, 217, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 169, 170, 0, 186, 0, 17, 0, 19, 182, + 0, 186, 0, 0, 186, 0, 0, 200, 0, 188, + 0, 181, 0, 0, 0, 0, 0, 126, 127, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 128, 129, 130, 131, 132, 0, 199, 219, 198, 0, + 185, 190, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 0, 0, 0, 45, 50, 0, 46, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 0, 0, 0, 201, 202, 0, 203, + 204, 0, 209, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 0, 0, 0, 197, 171, 186, 52, + 48, 0, 0, 72, 0, 73, 0, 0, 0, 58, + 0, 0, 0, 0, 0, 85, 86, 87, 89, 0, + 90, 186, 186, 0, 0, 193, 203, 204, 209, 110, + 112, 53, 49, 61, 62, 63, 59, 60, 0, 0, + 0, 0, 0, 111, 113, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 173, 186, 0, + 175, 186, 0, 0, 0, 114, 0, 51, 47, 67, + 0, 0, 0, 0, 0, 55, 56, 57, 0, 0, + 0, 84, 83, 88, 0, 0, 191, 0, 98, 0, + 0, 0, 0, 99, 105, 106, 107, 108, 109, 100, + 101, 102, 104, 103, 0, 0, 0, 0, 0, 0, + 186, 172, 74, 0, 0, 0, 97, 0, 0, 0, + 0, 0, 192, 0, 0, 0, 0, 186, 174, 186, + 176, 186, 226, 0, 75, 0, 77, 96, 0, 0, + 0, 82, 91, 92, 0, 0, 186, 0, 186, 0, + 186, 0, 0, 0, 177, 0, 0, 58, 0, 0, + 64, 66, 185, 69, 185, 71, 185, 178, 179, 180, + 76, 78, 0, 80, 0, 0, 0, 0, 0, 0, + 65, 68, 70, 79, 81 + }; + + const short + parser::yypgoto_[] = + { + -287, -287, -287, 295, 336, 338, -287, -287, -287, -194, + 122, -287, -287, -287, -93, -87, -287, -287, -287, -287, + -287, -287, -287, -287, -287, -287, -287, -287, -287, -287, + -287, -287, -287, -287, -287, -287, -287, -287, -287, -287, + 189, -287, -286, -277, -274, -287, -287, -287, -287, -287, + -287, -49, -11, -67, -58, -287, -287, 95, -43, -287, + -287, -287, -16, 197, 324, -287, 302, 355, -287, -287, + -287, 380, 417, 452, 490, -287, -287, -287, 0, 7, + -287, -15, -287, -287, 148, -287, -287 + }; + + const short + parser::yydefgoto_[] = + { + 0, 8, 9, 10, 11, 12, 13, 14, 15, 224, + 225, 281, 226, 227, 228, 354, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 106, 418, 253, 254, 255, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 32, 107, 200, 69, + 258, 304, 305, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 198, 84, 85, + 86, 87, 88, 89, 90, 91, 92 + }; + + const short + parser::yytable_[] = + { + 16, 158, 116, 355, 108, 6, 31, 151, 280, 16, + 19, 20, 356, 287, 96, 357, 152, 1, 2, 3, + 4, 5, 35, 36, 6, 38, 33, 196, 21, 6, + 42, 43, 44, 45, 112, 97, 100, 22, 113, 397, + 117, 94, 98, 101, 26, 30, 95, 284, 109, 28, + 6, 126, 29, 6, 151, 17, 53, 285, 127, 99, + 154, 108, 128, 152, 93, -196, -196, 398, 319, 320, + 27, 321, 322, 102, 153, 7, 292, 156, 197, 17, + 53, 127, 30, 114, 115, 56, -222, 348, 277, 366, + 367, 35, 36, 170, 38, 159, 131, 132, 6, 155, + 17, 53, 17, 18, 7, 160, 337, 149, 256, 340, + 174, 170, 391, 400, 170, 323, 324, 170, 170, -194, + -194, 153, 144, 145, 146, 147, 148, 161, 127, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + 401, 162, 408, -195, -195, 170, 257, 170, 17, 53, + 157, 355, 164, 256, 410, 201, 434, 262, 256, 170, + 356, 170, 265, 357, 127, 268, 447, 146, 147, 148, + 163, 170, 116, 116, 116, 274, 448, 256, 449, 35, + 36, 170, 38, 170, 165, 166, 6, 42, 43, 44, + 45, 257, 170, 171, 151, 303, 257, 293, 173, 414, + 175, 416, 262, 152, 154, 197, 278, 262, 283, 127, + 117, 117, 117, 286, 127, 257, 57, 288, 289, 290, + 291, 308, 262, 262, 295, 301, 262, 302, 127, 127, + 127, 296, 256, 127, 297, 103, 17, 53, 110, 111, + 116, 450, 151, 151, 453, 300, 313, 314, 118, 199, + 315, 152, 152, 316, 317, 318, 264, 338, 341, 267, + 344, 153, 350, 352, 463, 464, 115, 384, 127, 361, + 257, 144, 145, 146, 147, 148, 362, 369, 117, 370, + 371, 262, 372, 386, 390, 392, 388, 394, 127, 262, + 359, 151, 407, 169, 409, 396, 127, 411, 435, 422, + 152, 172, 439, 423, 23, 437, 421, 455, 440, 153, + 153, 441, 443, 445, 451, 456, 127, 127, 116, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 457, + 458, 460, 461, 462, 256, 24, 256, 25, 312, 263, + 452, 402, 266, 120, 259, 269, 117, 270, 153, 272, + 294, 0, 273, 0, 0, 127, 0, 308, 0, 0, + 0, 0, 0, 346, 127, 119, 0, 0, 0, 0, + 0, 0, 257, 442, 257, 444, 256, 446, 116, 256, + 0, 0, 282, 262, 0, 262, 364, 365, 420, 259, + 127, 0, 127, 0, 259, 299, 121, 0, 0, 256, + 256, 0, 0, 0, 0, 0, 0, 0, 306, 259, + 259, 0, 0, 259, 257, 0, 117, 257, 0, 0, + 0, 122, 0, 385, 0, 262, 387, 262, 262, 0, + 0, 0, 127, 0, 127, 127, 0, 257, 257, 0, + 0, 0, 0, -201, -201, 0, -201, 0, 262, 262, + -201, 0, 0, 0, 345, 127, 127, 0, 123, -201, + 0, 0, -201, 0, 0, 351, 0, 353, 259, 0, + 360, 260, 0, 0, 0, 413, 259, 0, 0, 0, + 0, 0, 273, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 431, 124, 432, 0, 433, 368, 0, 0, + -201, -201, 261, 0, 373, 374, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 0, 260, 0, 0, 0, + 0, 260, 389, 0, 0, 0, 0, 122, 0, 0, + 0, 125, 0, 0, 0, 307, 260, 260, 0, 0, + 260, 0, 0, 0, 0, 0, 0, 261, 403, 404, + 405, 406, 261, 0, 306, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 0, 121, 309, 310, 0, + 0, 261, 122, 415, 0, 417, 419, 122, 35, 36, + 259, 38, 259, 0, 0, 6, 42, 43, 44, 45, + 0, 122, 122, 122, 113, 260, 122, 0, 0, 124, + 0, 0, 0, 260, -209, -209, 0, -209, 0, 123, + 0, -209, 0, 0, 123, 0, 154, 0, 454, 0, + -209, 0, 259, -209, 259, 259, 261, 0, 123, 123, + 123, 0, 0, 123, 358, 17, 53, 125, 0, 0, + 0, 0, 0, 0, 124, 259, 259, 0, 0, 124, + 0, 122, 0, 0, 0, 0, 0, 0, 0, 122, + 0, -209, -209, 124, 124, 124, 0, 0, 124, 35, + 36, 0, 38, 0, 0, 0, 6, 42, 43, 44, + 45, 307, 125, 0, 0, 221, 0, 125, 123, 0, + 0, 0, 0, 222, 223, 0, 123, -202, -202, 0, + -202, 125, 125, 125, -202, 0, 125, 260, 0, 260, + 0, 0, 121, -202, 0, 0, -202, 0, 0, 0, + 0, 0, 0, 124, 0, 0, 17, 53, 0, -203, + -203, 124, -203, 0, 0, 0, -203, 122, 261, 0, + 261, 0, 0, 0, 0, -203, 0, 0, -203, 260, + 0, 260, 260, 0, -202, -202, 0, 0, 0, -204, + -204, 125, -204, 122, 0, 122, -204, 0, 0, 125, + 0, 0, 260, 260, 123, -204, 0, 0, -204, 0, + 261, 0, 358, 261, 131, 132, -203, -203, 135, 136, + 137, 138, 139, 140, 0, 0, 0, 0, 0, 0, + 123, 0, 123, 261, 261, 122, 0, 122, 122, 124, + 144, 145, 146, 147, 148, 0, -204, -204, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 34, 122, 122, + 0, 0, 0, 0, 0, 124, 0, 124, 0, 0, + 0, 0, 123, 0, 123, 123, 0, 125, 0, 0, + 0, 35, 36, 37, 38, 39, 40, 41, 6, 42, + 43, 44, 45, 46, 0, 123, 123, 104, 105, 0, + 0, 48, 0, 125, 0, 125, 0, 124, 0, 124, + 124, 0, 0, 0, 0, 0, 0, 49, 50, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 124, 124, 0, 0, 51, 0, 0, 52, 17, 53, + 30, 54, 55, 56, 0, 125, 0, 125, 125, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, + 0, 0, 0, 0, 0, 0, 0, 203, 125, 125, + 204, 205, 206, 0, 207, 208, 209, 210, 0, 211, + 212, 213, 214, 215, 216, 217, 218, 219, 35, 36, + 0, 38, 0, 0, 0, 6, 42, 43, 44, 45, + 0, 0, 157, 220, 221, 0, 0, 0, 0, 0, + 0, 202, 222, 223, 0, 0, 0, 0, 0, 203, + 0, 0, 204, 205, 206, 0, 207, 208, 209, 210, + 0, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 35, 36, 0, 38, 0, 17, 53, 6, 42, 43, + 44, 45, 0, 0, 157, 311, 221, 0, 0, 0, + 0, 0, 0, 0, 222, 223, 0, 0, 0, 0, + 0, 0, 35, 36, 0, 38, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 149, 279, + 0, 150, 0, 0, 0, 0, 203, 17, 53, 204, + 205, 206, 0, 207, 208, 209, 210, 0, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 35, 36, 0, + 38, 0, 0, 0, 6, 42, 43, 44, 45, 17, + 53, 157, 0, 221, 0, 0, 0, 0, 0, 0, + 0, 222, 223, 0, 0, 0, 0, 0, 0, -205, + -205, 0, -205, 0, 0, 0, -205, 0, 0, 0, + 0, 0, 0, 0, 0, -205, 347, 0, -205, 0, + 0, 0, 0, 203, 17, 53, 204, 205, 206, 0, + 207, 208, 209, 210, 0, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 35, 36, 34, 38, 0, 0, + 0, 6, 42, 43, 44, 45, -205, -205, 157, 0, + 221, 0, 0, 0, 0, 0, 0, 0, 222, 223, + 35, 36, 37, 38, 39, 40, 41, 6, 42, 43, + 44, 45, 46, 0, 0, 0, 47, 0, 0, 0, + 48, 0, 298, 0, 0, 0, 0, -206, -206, 0, + -206, 17, 53, 0, -206, 0, 49, 50, 0, 34, + 0, 0, 0, -206, 0, 0, -206, 0, 0, 0, + 0, 0, 0, 51, 0, 0, 52, 17, 53, 30, + 54, 55, 56, 35, 36, 37, 38, 39, 40, 41, + 6, 42, 43, 44, 45, 46, 0, 0, 0, 47, + 0, 0, 0, 48, -206, -206, 0, -207, -207, 0, + -207, 0, 0, 0, -207, 0, 0, 0, 0, 49, + 50, 0, 34, -207, 0, 0, -207, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 51, 0, 0, 52, + 17, 53, 30, 54, 55, 56, 35, 36, 37, 38, + 39, 40, 41, 6, 42, 43, 44, 45, 46, 0, + 0, 0, 104, 0, -207, -207, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -208, -208, 0, + -208, 0, 49, 50, -208, 0, 0, 0, 0, 0, + 0, 0, 0, -208, 0, 0, -208, 0, 0, 51, + 0, 0, 52, 17, 53, 30, 54, 55, 56, 203, + 0, 0, 204, 205, 206, 0, 207, 208, 209, 210, + 0, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 35, 36, 0, 38, -208, -208, 0, 6, 42, 43, + 44, 45, 0, 0, 157, 0, 221, 0, 0, 0, + 0, 0, 0, 0, 222, 223, 35, 36, 0, 38, + 0, 0, 0, 6, 0, 0, 35, 36, 0, 38, + 0, 0, 149, 6, 0, 174, 0, 0, 0, 0, + 323, 324, 149, 0, 0, 174, 0, 17, 53, 0, + 0, 0, 0, 0, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 0, 0, 0, 0, 0, + 0, 0, 167, 17, 53, 0, 0, 168, 0, 0, + 0, 0, 130, 17, 53, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 141, 142, + 143, 144, 145, 146, 147, 148, 425, 0, 0, 0, + 0, 426, 0, 0, 0, 0, 130, 0, 0, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 141, 142, 143, 144, 145, 146, 147, 148, + 427, 0, 0, 0, 0, 428, 0, 0, 0, 0, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 429, 0, 0, 0, 0, 430, + 0, 0, 0, 0, 130, 0, 0, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 167, 0, + 141, 142, 143, 144, 145, 146, 147, 148, 130, 0, + 0, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 393, 0, 141, 142, 143, 144, 145, 146, + 147, 148, 130, 0, 0, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 141, 142, + 143, 144, 145, 146, 147, 148, 130, 0, 0, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 399, 0, 141, 142, 143, 144, 145, 146, 147, 148, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 412, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 130, 0, 0, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 424, 0, + 141, 142, 143, 144, 145, 146, 147, 148, 130, 0, + 0, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 436, 0, 141, 142, 143, 144, 145, 146, + 147, 148, 130, 0, 0, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 438, 0, 141, 142, + 143, 144, 145, 146, 147, 148, 130, 0, 0, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 459, 0, 141, 142, 143, 144, 145, 146, 147, 148, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 271, 0, 0, 0, 0, 0, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 276, 0, 0, 0, 0, 0, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 336, 0, 0, 0, 0, 0, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 339, 0, 0, 0, 0, 0, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 342, 0, 0, 0, 0, 0, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 343, 0, 0, 0, 0, 130, + 0, 0, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 141, 142, 143, 144, 145, + 146, 147, 148, 275, 0, 130, 0, 0, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 142, 143, 144, 145, 146, 147, 148, 129, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 146, 147, 148, 349, 130, 0, 0, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 142, 143, 144, 145, 146, 147, 148, 363, + 130, 0, 0, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 130, 0, 0, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 0, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 146, 147, 148, 131, 132, 0, + 134, 135, 136, 137, 138, 139, 140, 131, 132, 0, + 0, 135, 136, 137, 138, 139, 140, 0, 0, 0, + 141, 142, 143, 144, 145, 146, 147, 148, 0, 0, + 141, 142, 143, 144, 145, 146, 147, 148, 131, 132, + 0, 0, 135, 136, 137, 138, 139, 140, 131, 132, + 0, 0, 135, 136, 137, 138, 139, 140, 0, 0, + 0, 0, 142, 143, 144, 145, 146, 147, 148, 0, + 0, 0, 142, 0, 144, 145, 146, 147, 148, 131, + 132, 0, 0, 0, 0, 137, 138, 139, 140, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 144, 145, 146, 147, 148 + }; + + const short + parser::yycheck_[] = + { + 0, 94, 51, 289, 47, 47, 21, 74, 202, 9, + 3, 4, 289, 207, 56, 289, 74, 11, 12, 13, + 14, 15, 40, 41, 47, 43, 26, 47, 52, 47, + 48, 49, 50, 51, 52, 35, 36, 0, 56, 30, + 51, 53, 35, 36, 52, 99, 58, 52, 48, 62, + 47, 51, 62, 47, 121, 97, 98, 62, 51, 56, + 52, 104, 98, 121, 53, 57, 58, 58, 17, 18, + 78, 20, 21, 56, 74, 98, 93, 62, 98, 97, + 98, 74, 99, 101, 102, 102, 60, 281, 53, 57, + 58, 40, 41, 58, 43, 95, 66, 67, 47, 60, + 97, 98, 97, 98, 98, 56, 53, 56, 157, 53, + 59, 58, 53, 53, 58, 64, 65, 58, 58, 57, + 58, 121, 92, 93, 94, 95, 96, 52, 121, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 53, 60, 53, 57, 58, 58, 157, 58, 97, 98, + 54, 437, 52, 202, 53, 155, 53, 157, 207, 58, + 437, 58, 162, 437, 157, 165, 53, 94, 95, 96, + 56, 58, 221, 222, 223, 175, 53, 226, 53, 40, + 41, 58, 43, 58, 60, 56, 47, 48, 49, 50, + 51, 202, 58, 57, 261, 56, 207, 212, 56, 393, + 60, 395, 202, 261, 52, 98, 52, 207, 62, 202, + 221, 222, 223, 52, 207, 226, 27, 52, 52, 52, + 52, 221, 222, 223, 61, 52, 226, 52, 221, 222, + 223, 62, 281, 226, 62, 46, 97, 98, 49, 50, + 289, 435, 309, 310, 438, 62, 62, 62, 51, 154, + 62, 309, 310, 62, 62, 78, 161, 52, 52, 164, + 57, 261, 53, 27, 458, 459, 102, 57, 261, 61, + 281, 92, 93, 94, 95, 96, 61, 52, 289, 52, + 52, 281, 52, 57, 52, 62, 57, 52, 281, 289, + 290, 358, 52, 104, 52, 62, 289, 52, 25, 62, + 358, 112, 30, 62, 9, 62, 399, 53, 62, 309, + 310, 62, 62, 62, 62, 53, 309, 310, 367, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 53, + 53, 62, 62, 62, 393, 9, 395, 9, 226, 160, + 437, 367, 163, 51, 157, 166, 367, 168, 358, 170, + 212, -1, 173, -1, -1, 358, -1, 367, -1, -1, + -1, -1, -1, 278, 367, 51, -1, -1, -1, -1, + -1, -1, 393, 426, 395, 428, 435, 430, 437, 438, + -1, -1, 203, 393, -1, 395, 301, 302, 398, 202, + 393, -1, 395, -1, 207, 216, 51, -1, -1, 458, + 459, -1, -1, -1, -1, -1, -1, -1, 221, 222, + 223, -1, -1, 226, 435, -1, 437, 438, -1, -1, + -1, 51, -1, 338, -1, 435, 341, 437, 438, -1, + -1, -1, 435, -1, 437, 438, -1, 458, 459, -1, + -1, -1, -1, 40, 41, -1, 43, -1, 458, 459, + 47, -1, -1, -1, 275, 458, 459, -1, 51, 56, + -1, -1, 59, -1, -1, 286, -1, 288, 281, -1, + 291, 157, -1, -1, -1, 390, 289, -1, -1, -1, + -1, -1, 303, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 407, 51, 409, -1, 411, 318, -1, -1, + 97, 98, 157, -1, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 202, -1, -1, -1, + -1, 207, 343, -1, -1, -1, -1, 157, -1, -1, + -1, 51, -1, -1, -1, 221, 222, 223, -1, -1, + 226, -1, -1, -1, -1, -1, -1, 202, 369, 370, + 371, 372, 207, -1, 367, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 157, -1, 221, 222, 223, -1, + -1, 226, 202, 394, -1, 396, 397, 207, 40, 41, + 393, 43, 395, -1, -1, 47, 48, 49, 50, 51, + -1, 221, 222, 223, 56, 281, 226, -1, -1, 157, + -1, -1, -1, 289, 40, 41, -1, 43, -1, 202, + -1, 47, -1, -1, 207, -1, 52, -1, 439, -1, + 56, -1, 435, 59, 437, 438, 281, -1, 221, 222, + 223, -1, -1, 226, 289, 97, 98, 157, -1, -1, + -1, -1, -1, -1, 202, 458, 459, -1, -1, 207, + -1, 281, -1, -1, -1, -1, -1, -1, -1, 289, + -1, 97, 98, 221, 222, 223, -1, -1, 226, 40, + 41, -1, 43, -1, -1, -1, 47, 48, 49, 50, + 51, 367, 202, -1, -1, 56, -1, 207, 281, -1, + -1, -1, -1, 64, 65, -1, 289, 40, 41, -1, + 43, 221, 222, 223, 47, -1, 226, 393, -1, 395, + -1, -1, 367, 56, -1, -1, 59, -1, -1, -1, + -1, -1, -1, 281, -1, -1, 97, 98, -1, 40, + 41, 289, 43, -1, -1, -1, 47, 367, 393, -1, + 395, -1, -1, -1, -1, 56, -1, -1, 59, 435, + -1, 437, 438, -1, 97, 98, -1, -1, -1, 40, + 41, 281, 43, 393, -1, 395, 47, -1, -1, 289, + -1, -1, 458, 459, 367, 56, -1, -1, 59, -1, + 435, -1, 437, 438, 66, 67, 97, 98, 70, 71, + 72, 73, 74, 75, -1, -1, -1, -1, -1, -1, + 393, -1, 395, 458, 459, 435, -1, 437, 438, 367, + 92, 93, 94, 95, 96, -1, 97, 98, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 16, 458, 459, + -1, -1, -1, -1, -1, 393, -1, 395, -1, -1, + -1, -1, 435, -1, 437, 438, -1, 367, -1, -1, + -1, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, -1, 458, 459, 56, 57, -1, + -1, 60, -1, 393, -1, 395, -1, 435, -1, 437, + 438, -1, -1, -1, -1, -1, -1, 76, 77, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 458, 459, -1, -1, 93, -1, -1, 96, 97, 98, + 99, 100, 101, 102, -1, 435, -1, 437, 438, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, + -1, -1, -1, -1, -1, -1, -1, 19, 458, 459, + 22, 23, 24, -1, 26, 27, 28, 29, -1, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + -1, 43, -1, -1, -1, 47, 48, 49, 50, 51, + -1, -1, 54, 55, 56, -1, -1, -1, -1, -1, + -1, 11, 64, 65, -1, -1, -1, -1, -1, 19, + -1, -1, 22, 23, 24, -1, 26, 27, 28, 29, + -1, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, -1, 43, -1, 97, 98, 47, 48, 49, + 50, 51, -1, -1, 54, 55, 56, -1, -1, -1, + -1, -1, -1, -1, 64, 65, -1, -1, -1, -1, + -1, -1, 40, 41, -1, 43, -1, -1, -1, 47, + -1, -1, -1, -1, -1, -1, -1, -1, 56, 12, + -1, 59, -1, -1, -1, -1, 19, 97, 98, 22, + 23, 24, -1, 26, 27, 28, 29, -1, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, -1, + 43, -1, -1, -1, 47, 48, 49, 50, 51, 97, + 98, 54, -1, 56, -1, -1, -1, -1, -1, -1, + -1, 64, 65, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, 56, 12, -1, 59, -1, + -1, -1, -1, 19, 97, 98, 22, 23, 24, -1, + 26, 27, 28, 29, -1, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 16, 43, -1, -1, + -1, 47, 48, 49, 50, 51, 97, 98, 54, -1, + 56, -1, -1, -1, -1, -1, -1, -1, 64, 65, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, -1, -1, -1, 56, -1, -1, -1, + 60, -1, 62, -1, -1, -1, -1, 40, 41, -1, + 43, 97, 98, -1, 47, -1, 76, 77, -1, 16, + -1, -1, -1, 56, -1, -1, 59, -1, -1, -1, + -1, -1, -1, 93, -1, -1, 96, 97, 98, 99, + 100, 101, 102, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, -1, -1, -1, 56, + -1, -1, -1, 60, 97, 98, -1, 40, 41, -1, + 43, -1, -1, -1, 47, -1, -1, -1, -1, 76, + 77, -1, 16, 56, -1, -1, 59, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 93, -1, -1, 96, + 97, 98, 99, 100, 101, 102, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, -1, + -1, -1, 56, -1, 97, 98, 60, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, -1, 76, 77, 47, -1, -1, -1, -1, -1, + -1, -1, -1, 56, -1, -1, 59, -1, -1, 93, + -1, -1, 96, 97, 98, 99, 100, 101, 102, 19, + -1, -1, 22, 23, 24, -1, 26, 27, 28, 29, + -1, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, -1, 43, 97, 98, -1, 47, 48, 49, + 50, 51, -1, -1, 54, -1, 56, -1, -1, -1, + -1, -1, -1, -1, 64, 65, 40, 41, -1, 43, + -1, -1, -1, 47, -1, -1, 40, 41, -1, 43, + -1, -1, 56, 47, -1, 59, -1, -1, -1, -1, + 64, 65, 56, -1, -1, 59, -1, 97, 98, -1, + -1, -1, -1, -1, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, -1, -1, -1, -1, -1, + -1, -1, 53, 97, 98, -1, -1, 58, -1, -1, + -1, -1, 63, 97, 98, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 89, 90, + 91, 92, 93, 94, 95, 96, 53, -1, -1, -1, + -1, 58, -1, -1, -1, -1, 63, -1, -1, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 89, 90, 91, 92, 93, 94, 95, 96, + 53, -1, -1, -1, -1, 58, -1, -1, -1, -1, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 53, -1, -1, -1, -1, 58, + -1, -1, -1, -1, 63, -1, -1, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 53, -1, + 89, 90, 91, 92, 93, 94, 95, 96, 63, -1, + -1, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 53, -1, 89, 90, 91, 92, 93, 94, + 95, 96, 63, -1, -1, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 53, -1, 89, 90, + 91, 92, 93, 94, 95, 96, 63, -1, -1, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 53, -1, 89, 90, 91, 92, 93, 94, 95, 96, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 53, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 63, -1, -1, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 53, -1, + 89, 90, 91, 92, 93, 94, 95, 96, 63, -1, + -1, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 53, -1, 89, 90, 91, 92, 93, 94, + 95, 96, 63, -1, -1, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 53, -1, 89, 90, + 91, 92, 93, 94, 95, 96, 63, -1, -1, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 53, -1, 89, 90, 91, 92, 93, 94, 95, 96, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 57, -1, -1, -1, -1, -1, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 57, -1, -1, -1, -1, -1, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 57, -1, -1, -1, -1, -1, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 57, -1, -1, -1, -1, -1, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 57, -1, -1, -1, -1, -1, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 58, -1, -1, -1, -1, 63, + -1, -1, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 89, 90, 91, 92, 93, + 94, 95, 96, 61, -1, 63, -1, -1, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 89, 90, 91, 92, 93, 94, 95, 96, 62, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 89, 90, 91, 92, + 93, 94, 95, 96, 62, 63, -1, -1, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 89, 90, 91, 92, 93, 94, 95, 96, 62, + 63, -1, -1, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 63, -1, -1, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 89, 90, 91, 92, + 93, 94, 95, 96, -1, -1, -1, -1, -1, 89, + 90, 91, 92, 93, 94, 95, 96, 66, 67, -1, + 69, 70, 71, 72, 73, 74, 75, 66, 67, -1, + -1, 70, 71, 72, 73, 74, 75, -1, -1, -1, + 89, 90, 91, 92, 93, 94, 95, 96, -1, -1, + 89, 90, 91, 92, 93, 94, 95, 96, 66, 67, + -1, -1, 70, 71, 72, 73, 74, 75, 66, 67, + -1, -1, 70, 71, 72, 73, 74, 75, -1, -1, + -1, -1, 90, 91, 92, 93, 94, 95, 96, -1, + -1, -1, 90, -1, 92, 93, 94, 95, 96, 66, + 67, -1, -1, -1, -1, 72, 73, 74, 75, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 92, 93, 94, 95, 96 + }; + + const unsigned char + parser::yystos_[] = + { + 0, 11, 12, 13, 14, 15, 47, 98, 114, 115, + 116, 117, 118, 119, 120, 121, 191, 97, 98, 192, + 192, 52, 0, 116, 117, 118, 52, 78, 62, 62, + 99, 194, 169, 191, 16, 40, 41, 42, 43, 44, + 45, 46, 48, 49, 50, 51, 52, 56, 60, 76, + 77, 93, 96, 98, 100, 101, 102, 153, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 172, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 53, 53, 58, 56, 191, 192, 56, + 191, 192, 56, 153, 56, 57, 153, 170, 171, 191, + 153, 153, 52, 56, 101, 102, 164, 165, 176, 177, + 179, 180, 184, 185, 186, 187, 191, 192, 98, 62, + 63, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 89, 90, 91, 92, 93, 94, 95, 96, 56, + 59, 166, 167, 191, 52, 60, 62, 54, 127, 191, + 56, 52, 60, 56, 52, 60, 56, 53, 58, 153, + 58, 57, 153, 56, 59, 60, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 47, 98, 190, 170, + 171, 191, 11, 19, 22, 23, 24, 26, 27, 28, + 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 55, 56, 64, 65, 122, 123, 125, 126, 127, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 155, 156, 157, 164, 165, 173, 176, + 177, 180, 191, 153, 170, 191, 153, 170, 191, 153, + 153, 57, 153, 153, 191, 61, 57, 53, 52, 12, + 122, 124, 153, 62, 52, 62, 52, 122, 52, 52, + 52, 52, 93, 194, 197, 61, 62, 62, 62, 153, + 62, 52, 52, 56, 174, 175, 176, 177, 191, 180, + 180, 55, 123, 62, 62, 62, 62, 62, 78, 17, + 18, 20, 21, 64, 65, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 57, 53, 52, 57, + 53, 52, 57, 58, 57, 153, 170, 12, 122, 62, + 53, 153, 27, 153, 128, 155, 156, 157, 180, 191, + 153, 61, 61, 62, 170, 170, 57, 58, 153, 52, + 52, 52, 52, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 57, 170, 57, 170, 57, 153, + 52, 53, 62, 53, 52, 53, 62, 30, 58, 53, + 53, 53, 175, 153, 153, 153, 153, 52, 53, 52, + 53, 52, 53, 170, 122, 153, 122, 153, 154, 153, + 191, 127, 62, 62, 53, 53, 58, 53, 58, 53, + 58, 170, 170, 170, 53, 25, 53, 62, 53, 30, + 62, 62, 171, 62, 171, 62, 171, 53, 53, 53, + 122, 62, 128, 122, 153, 53, 53, 53, 53, 53, + 62, 62, 62, 122, 122 + }; + + const unsigned char + parser::yyr1_[] = + { + 0, 113, 114, 114, 115, 115, 115, 115, 115, 115, + 116, 117, 118, 118, 118, 118, 118, 119, 120, 121, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 123, 123, 124, 124, 125, + 125, 126, 126, 127, 127, 128, 128, 128, 128, 129, + 129, 130, 130, 130, 131, 132, 132, 133, 134, 134, + 135, 135, 136, 137, 137, 138, 139, 140, 141, 142, + 143, 143, 144, 145, 145, 146, 147, 148, 149, 149, + 150, 151, 152, 153, 153, 153, 154, 154, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 156, 156, 157, 157, 158, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 161, 162, 162, 162, 162, 163, 164, 164, 165, + 165, 166, 166, 166, 166, 166, 166, 167, 167, 167, + 167, 168, 169, 169, 169, 170, 170, 171, 171, 172, + 172, 173, 174, 174, 175, 175, 175, 176, 177, 178, + 179, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 191, 192, 192, 193, 194, 195, 196, 196, 197, + 197, 198, 199 + }; + + const signed char + parser::yyr2_[] = + { + 0, 2, 1, 0, 2, 2, 2, 1, 1, 1, + 3, 3, 1, 1, 1, 1, 1, 5, 4, 5, + 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, 1, 2, + 1, 3, 2, 3, 2, 1, 1, 1, 0, 2, + 2, 2, 2, 2, 6, 8, 6, 3, 8, 6, + 8, 6, 2, 2, 4, 5, 7, 5, 7, 9, + 7, 9, 5, 3, 3, 2, 2, 2, 3, 2, + 2, 5, 5, 1, 1, 1, 1, 0, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 5, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 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, 2, 2, 1, 1, 2, + 2, 4, 6, 5, 7, 5, 7, 8, 9, 9, + 9, 3, 3, 1, 0, 1, 0, 3, 1, 2, + 3, 3, 3, 1, 1, 1, 1, 4, 3, 3, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 7, 2, 1, 2, + 1, 1, 1 + }; + + + + +#if S1CDEBUG + const short + parser::yyrline_[] = + { + 0, 263, 263, 264, 268, 270, 272, 274, 276, 278, + 283, 287, 292, 293, 294, 295, 296, 300, 305, 310, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 343, 344, 348, 350, 355, + 357, 362, 363, 367, 368, 372, 374, 376, 379, 383, + 385, 390, 392, 394, 399, 404, 406, 411, 416, 418, + 423, 425, 430, 435, 437, 442, 447, 452, 457, 462, + 467, 469, 474, 479, 481, 486, 491, 496, 501, 503, + 508, 513, 518, 523, 524, 525, 529, 530, 534, 536, + 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, + 561, 563, 568, 570, 575, 580, 582, 584, 586, 588, + 590, 592, 594, 596, 598, 600, 602, 604, 606, 608, + 610, 612, 614, 619, 620, 621, 622, 623, 624, 625, + 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, + 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, + 646, 650, 655, 657, 659, 661, 666, 671, 672, 675, + 676, 680, 682, 684, 686, 688, 690, 695, 697, 699, + 701, 706, 711, 713, 716, 720, 723, 727, 729, 734, + 736, 741, 746, 748, 753, 754, 755, 759, 764, 769, + 774, 779, 780, 781, 782, 783, 784, 785, 786, 787, + 791, 796, 801, 806, 811, 816, 821, 826, 831, 836, + 841, 843, 848, 850, 855, 860, 865, 870, 872, 877, + 879, 884, 889 + }; + + 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 // S1CDEBUG + + +#line 13 "parser.ypp" +} } } // xsk::gsc::s1c +#line 4726 "parser.cpp" + +#line 893 "parser.ypp" + + +void xsk::gsc::s1c::parser::error(const xsk::gsc::location& loc, const std::string& msg) +{ + throw xsk::gsc::comp_error(loc, msg); +} diff --git a/src/experimental/s1c/xsk/parser.hpp b/src/experimental/s1c/xsk/parser.hpp new file mode 100644 index 00000000..8faccf8b --- /dev/null +++ b/src/experimental/s1c/xsk/parser.hpp @@ -0,0 +1,5601 @@ +// A Bison parser, made by GNU Bison 3.8.2. + +// 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::s1c::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_S1C_PARSER_HPP_INCLUDED +# define YY_S1C_PARSER_HPP_INCLUDED +// "%code requires" blocks. +#line 28 "parser.ypp" + +#ifdef _MSC_VER +#pragma warning(disable:4065) +#pragma warning(disable:4127) +#endif +#include "s1c.hpp" +namespace xsk::gsc::s1c { class lexer; } + +#line 58 "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 S1C_ASSERT +# include +# define S1C_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 + +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# 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 S1CDEBUG +# if defined YYDEBUG +#if YYDEBUG +# define S1CDEBUG 1 +# else +# define S1CDEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define S1CDEBUG 1 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined S1CDEBUG */ + +#line 13 "parser.ypp" +namespace xsk { namespace gsc { namespace s1c { +#line 207 "parser.hpp" + + + + + /// A Bison parser. + class parser + { + public: +#ifdef S1CSTYPE +# ifdef __GNUC__ +# pragma GCC message "bison: do not #define S1CSTYPE in C++, use %define api.value.type" +# endif + typedef S1CSTYPE value_type; +#else + /// 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 value_type + { + public: + /// Type of *this. + typedef value_type self_type; + + /// Empty construction. + value_type () YY_NOEXCEPT + : yyraw_ () + , yytypeid_ (YY_NULLPTR) + {} + + /// Construct and fill. + template + value_type (YY_RVREF (T) t) + : yytypeid_ (&typeid (T)) + { + S1C_ASSERT (sizeof (T) <= size); + new (yyas_ ()) T (YY_MOVE (t)); + } + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + value_type (const self_type&) = delete; + /// Non copyable. + self_type& operator= (const self_type&) = delete; +#endif + + /// Destruction, allowed only if empty. + ~value_type () YY_NOEXCEPT + { + S1C_ASSERT (!yytypeid_); + } + +# if 201103L <= YY_CPLUSPLUS + /// Instantiate a \a T in here from \a t. + template + T& + emplace (U&&... u) + { + S1C_ASSERT (!yytypeid_); + S1C_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 () + { + S1C_ASSERT (!yytypeid_); + S1C_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) + { + S1C_ASSERT (!yytypeid_); + S1C_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 + { + S1C_ASSERT (yytypeid_); + S1C_ASSERT (*yytypeid_ == typeid (T)); + S1C_ASSERT (sizeof (T) <= size); + return *yyas_ (); + } + + /// Const accessor to a built \a T (for %printer). + template + const T& + as () const YY_NOEXCEPT + { + S1C_ASSERT (yytypeid_); + S1C_ASSERT (*yytypeid_ == typeid (T)); + S1C_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 + { + S1C_ASSERT (yytypeid_); + S1C_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. + value_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 = yyraw_; + return static_cast (yyp); + } + + /// Const accessor to raw memory as \a T. + template + const T* + yyas_ () const YY_NOEXCEPT + { + const void *yyp = yyraw_; + return static_cast (yyp); + } + + /// An auxiliary type to compute the largest semantic type. + union union_type + { + // expr_function + // expr_pointer + char dummy1[sizeof (ast::call)]; + + // declaration + char dummy2[sizeof (ast::decl)]; + + // decl_constant + char dummy3[sizeof (ast::decl_constant::ptr)]; + + // decl_thread + char dummy4[sizeof (ast::decl_thread::ptr)]; + + // decl_usingtree + char dummy5[sizeof (ast::decl_usingtree::ptr)]; + + // expr + // expr_or_empty + // expr_assign + // expr_increment + // expr_decrement + // expr_ternary + // expr_binary + // expr_primitive + // expr_tuple + // expr_tuple_types + // expr_object + char dummy6[sizeof (ast::expr)]; + + // expr_add_array + char dummy7[sizeof (ast::expr_add_array::ptr)]; + + // expr_anim + char dummy8[sizeof (ast::expr_anim::ptr)]; + + // expr_animation + char dummy9[sizeof (ast::expr_animation::ptr)]; + + // expr_animtree + char dummy10[sizeof (ast::expr_animtree::ptr)]; + + // expr_arguments + // expr_arguments_no_empty + char dummy11[sizeof (ast::expr_arguments::ptr)]; + + // expr_array + char dummy12[sizeof (ast::expr_array::ptr)]; + + // expr_call + char dummy13[sizeof (ast::expr_call::ptr)]; + + // expr_complement + char dummy14[sizeof (ast::expr_complement::ptr)]; + + // expr_empty_array + char dummy15[sizeof (ast::expr_empty_array::ptr)]; + + // expr_false + char dummy16[sizeof (ast::expr_false::ptr)]; + + // expr_field + char dummy17[sizeof (ast::expr_field::ptr)]; + + // expr_float + char dummy18[sizeof (ast::expr_float::ptr)]; + + // expr_game + char dummy19[sizeof (ast::expr_game::ptr)]; + + // expr_identifier_nosize + // expr_identifier + char dummy20[sizeof (ast::expr_identifier::ptr)]; + + // expr_integer + char dummy21[sizeof (ast::expr_integer::ptr)]; + + // expr_istring + char dummy22[sizeof (ast::expr_istring::ptr)]; + + // expr_level + char dummy23[sizeof (ast::expr_level::ptr)]; + + // expr_method + char dummy24[sizeof (ast::expr_method::ptr)]; + + // expr_negate + char dummy25[sizeof (ast::expr_negate::ptr)]; + + // expr_not + char dummy26[sizeof (ast::expr_not::ptr)]; + + // expr_parameters + char dummy27[sizeof (ast::expr_parameters::ptr)]; + + // expr_paren + char dummy28[sizeof (ast::expr_paren::ptr)]; + + // expr_path + char dummy29[sizeof (ast::expr_path::ptr)]; + + // expr_reference + char dummy30[sizeof (ast::expr_reference::ptr)]; + + // expr_self + char dummy31[sizeof (ast::expr_self::ptr)]; + + // expr_size + char dummy32[sizeof (ast::expr_size::ptr)]; + + // expr_string + char dummy33[sizeof (ast::expr_string::ptr)]; + + // expr_thisthread + char dummy34[sizeof (ast::expr_thisthread::ptr)]; + + // expr_true + char dummy35[sizeof (ast::expr_true::ptr)]; + + // expr_tuple_arguments + char dummy36[sizeof (ast::expr_tuple::ptr)]; + + // expr_undefined + char dummy37[sizeof (ast::expr_undefined::ptr)]; + + // expr_vector + char dummy38[sizeof (ast::expr_vector::ptr)]; + + // include + char dummy39[sizeof (ast::include::ptr)]; + + // program + char dummy40[sizeof (ast::program::ptr)]; + + // stmt + // stmt_or_dev + char dummy41[sizeof (ast::stmt)]; + + // stmt_assign + char dummy42[sizeof (ast::stmt_assign::ptr)]; + + // stmt_break + char dummy43[sizeof (ast::stmt_break::ptr)]; + + // stmt_breakpoint + char dummy44[sizeof (ast::stmt_breakpoint::ptr)]; + + // stmt_call + char dummy45[sizeof (ast::stmt_call::ptr)]; + + // stmt_case + char dummy46[sizeof (ast::stmt_case::ptr)]; + + // stmt_continue + char dummy47[sizeof (ast::stmt_continue::ptr)]; + + // stmt_default + char dummy48[sizeof (ast::stmt_default::ptr)]; + + // stmt_dev + char dummy49[sizeof (ast::stmt_dev::ptr)]; + + // stmt_dowhile + char dummy50[sizeof (ast::stmt_dowhile::ptr)]; + + // stmt_endon + char dummy51[sizeof (ast::stmt_endon::ptr)]; + + // stmt_expr + char dummy52[sizeof (ast::stmt_expr::ptr)]; + + // stmt_for + char dummy53[sizeof (ast::stmt_for::ptr)]; + + // stmt_foreach + char dummy54[sizeof (ast::stmt_foreach::ptr)]; + + // stmt_if + char dummy55[sizeof (ast::stmt_if::ptr)]; + + // stmt_ifelse + char dummy56[sizeof (ast::stmt_ifelse::ptr)]; + + // stmt_list + // stmt_or_dev_list + // stmt_block + char dummy57[sizeof (ast::stmt_list::ptr)]; + + // stmt_notify + char dummy58[sizeof (ast::stmt_notify::ptr)]; + + // stmt_prof_begin + char dummy59[sizeof (ast::stmt_prof_begin::ptr)]; + + // stmt_prof_end + char dummy60[sizeof (ast::stmt_prof_end::ptr)]; + + // stmt_return + char dummy61[sizeof (ast::stmt_return::ptr)]; + + // stmt_switch + char dummy62[sizeof (ast::stmt_switch::ptr)]; + + // stmt_wait + char dummy63[sizeof (ast::stmt_wait::ptr)]; + + // stmt_waitframe + char dummy64[sizeof (ast::stmt_waitframe::ptr)]; + + // stmt_waittill + char dummy65[sizeof (ast::stmt_waittill::ptr)]; + + // stmt_waittillframeend + char dummy66[sizeof (ast::stmt_waittillframeend::ptr)]; + + // stmt_waittillmatch + char dummy67[sizeof (ast::stmt_waittillmatch::ptr)]; + + // stmt_while + char dummy68[sizeof (ast::stmt_while::ptr)]; + + // "path" + // "identifier" + // "string literal" + // "localized string" + // "float" + // "integer" + char dummy69[sizeof (std::string)]; + }; + + /// 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]; + }; + + /// Whether the content is built: if defined, the name of the stored type. + const std::type_info *yytypeid_; + }; + +#endif + /// Backward compatibility (Bison 3.8). + typedef value_type semantic_type; + + /// 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 + { + S1CEMPTY = -2, + S1CEOF = 0, // "end of file" + S1Cerror = 1, // error + S1CUNDEF = 2, // "invalid token" + SH_DEFINE = 3, // "#define" + SH_UNDEF = 4, // "#undef" + SH_IFDEF = 5, // "#ifdef" + SH_IFNDEF = 6, // "#ifndef" + SH_IF = 7, // "#if" + SH_ELIF = 8, // "#elif" + SH_ELSE = 9, // "#else" + SH_ENDIF = 10, // "#endif" + DEVBEGIN = 11, // "/#" + DEVEND = 12, // "#/" + INLINE = 13, // "#inline" + INCLUDE = 14, // "#include" + USINGTREE = 15, // "#using_animtree" + ANIMTREE = 16, // "#animtree" + ENDON = 17, // "endon" + NOTIFY = 18, // "notify" + WAIT = 19, // "wait" + WAITTILL = 20, // "waittill" + WAITTILLMATCH = 21, // "waittillmatch" + WAITTILLFRAMEEND = 22, // "waittillframeend" + WAITFRAME = 23, // "waitframe" + IF = 24, // "if" + ELSE = 25, // "else" + DO = 26, // "do" + WHILE = 27, // "while" + FOR = 28, // "for" + FOREACH = 29, // "foreach" + IN = 30, // "in" + SWITCH = 31, // "switch" + CASE = 32, // "case" + DEFAULT = 33, // "default" + BREAK = 34, // "break" + CONTINUE = 35, // "continue" + RETURN = 36, // "return" + BREAKPOINT = 37, // "breakpoint" + PROFBEGIN = 38, // "prof_begin" + PROFEND = 39, // "prof_end" + THREAD = 40, // "thread" + CHILDTHREAD = 41, // "childthread" + THISTHREAD = 42, // "thisthread" + CALL = 43, // "call" + TRUE = 44, // "true" + FALSE = 45, // "false" + UNDEFINED = 46, // "undefined" + SIZE = 47, // "size" + GAME = 48, // "game" + SELF = 49, // "self" + ANIM = 50, // "anim" + LEVEL = 51, // "level" + LPAREN = 52, // "(" + RPAREN = 53, // ")" + LBRACE = 54, // "{" + RBRACE = 55, // "}" + LBRACKET = 56, // "[" + RBRACKET = 57, // "]" + COMMA = 58, // "," + DOT = 59, // "." + DOUBLECOLON = 60, // "::" + COLON = 61, // ":" + SEMICOLON = 62, // ";" + QMARK = 63, // "?" + INCREMENT = 64, // "++" + DECREMENT = 65, // "--" + LSHIFT = 66, // "<<" + RSHIFT = 67, // ">>" + OR = 68, // "||" + AND = 69, // "&&" + EQUALITY = 70, // "==" + INEQUALITY = 71, // "!=" + LESS_EQUAL = 72, // "<=" + GREATER_EQUAL = 73, // ">=" + LESS = 74, // "<" + GREATER = 75, // ">" + NOT = 76, // "!" + COMPLEMENT = 77, // "~" + ASSIGN = 78, // "=" + ASSIGN_ADD = 79, // "+=" + ASSIGN_SUB = 80, // "-=" + ASSIGN_MUL = 81, // "*=" + ASSIGN_DIV = 82, // "/=" + ASSIGN_MOD = 83, // "%=" + ASSIGN_BW_OR = 84, // "|=" + ASSIGN_BW_AND = 85, // "&=" + ASSIGN_BW_EXOR = 86, // "^=" + ASSIGN_RSHIFT = 87, // ">>=" + ASSIGN_LSHIFT = 88, // "<<=" + BITWISE_OR = 89, // "|" + BITWISE_AND = 90, // "&" + BITWISE_EXOR = 91, // "^" + ADD = 92, // "+" + SUB = 93, // "-" + MUL = 94, // "*" + DIV = 95, // "/" + MOD = 96, // "%" + PATH = 97, // "path" + IDENTIFIER = 98, // "identifier" + STRING = 99, // "string literal" + ISTRING = 100, // "localized string" + FLOAT = 101, // "float" + INTEGER = 102, // "integer" + SIZEOF = 103, // SIZEOF + ADD_ARRAY = 104, // ADD_ARRAY + THEN = 105, // THEN + TERN = 106, // TERN + NEG = 107, // NEG + ANIMREF = 108, // ANIMREF + PREINC = 109, // PREINC + PREDEC = 110, // PREDEC + POSTINC = 111, // POSTINC + POSTDEC = 112 // POSTDEC + }; + /// Backward compatibility alias (Bison 3.6). + typedef token_kind_type yytokentype; + }; + + /// Token kind, as returned by yylex. + typedef token::token_kind_type 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 = 113, ///< Number of tokens. + S_YYEMPTY = -2, + S_YYEOF = 0, // "end of file" + S_YYerror = 1, // error + S_YYUNDEF = 2, // "invalid token" + S_SH_DEFINE = 3, // "#define" + S_SH_UNDEF = 4, // "#undef" + S_SH_IFDEF = 5, // "#ifdef" + S_SH_IFNDEF = 6, // "#ifndef" + S_SH_IF = 7, // "#if" + S_SH_ELIF = 8, // "#elif" + S_SH_ELSE = 9, // "#else" + S_SH_ENDIF = 10, // "#endif" + S_DEVBEGIN = 11, // "/#" + S_DEVEND = 12, // "#/" + S_INLINE = 13, // "#inline" + S_INCLUDE = 14, // "#include" + S_USINGTREE = 15, // "#using_animtree" + S_ANIMTREE = 16, // "#animtree" + S_ENDON = 17, // "endon" + S_NOTIFY = 18, // "notify" + S_WAIT = 19, // "wait" + S_WAITTILL = 20, // "waittill" + S_WAITTILLMATCH = 21, // "waittillmatch" + S_WAITTILLFRAMEEND = 22, // "waittillframeend" + S_WAITFRAME = 23, // "waitframe" + S_IF = 24, // "if" + S_ELSE = 25, // "else" + S_DO = 26, // "do" + S_WHILE = 27, // "while" + S_FOR = 28, // "for" + S_FOREACH = 29, // "foreach" + S_IN = 30, // "in" + S_SWITCH = 31, // "switch" + S_CASE = 32, // "case" + S_DEFAULT = 33, // "default" + S_BREAK = 34, // "break" + S_CONTINUE = 35, // "continue" + S_RETURN = 36, // "return" + S_BREAKPOINT = 37, // "breakpoint" + S_PROFBEGIN = 38, // "prof_begin" + S_PROFEND = 39, // "prof_end" + S_THREAD = 40, // "thread" + S_CHILDTHREAD = 41, // "childthread" + S_THISTHREAD = 42, // "thisthread" + S_CALL = 43, // "call" + S_TRUE = 44, // "true" + S_FALSE = 45, // "false" + S_UNDEFINED = 46, // "undefined" + S_SIZE = 47, // "size" + S_GAME = 48, // "game" + S_SELF = 49, // "self" + S_ANIM = 50, // "anim" + S_LEVEL = 51, // "level" + S_LPAREN = 52, // "(" + S_RPAREN = 53, // ")" + S_LBRACE = 54, // "{" + S_RBRACE = 55, // "}" + S_LBRACKET = 56, // "[" + S_RBRACKET = 57, // "]" + S_COMMA = 58, // "," + S_DOT = 59, // "." + S_DOUBLECOLON = 60, // "::" + S_COLON = 61, // ":" + S_SEMICOLON = 62, // ";" + S_QMARK = 63, // "?" + S_INCREMENT = 64, // "++" + S_DECREMENT = 65, // "--" + S_LSHIFT = 66, // "<<" + S_RSHIFT = 67, // ">>" + S_OR = 68, // "||" + S_AND = 69, // "&&" + S_EQUALITY = 70, // "==" + S_INEQUALITY = 71, // "!=" + S_LESS_EQUAL = 72, // "<=" + S_GREATER_EQUAL = 73, // ">=" + S_LESS = 74, // "<" + S_GREATER = 75, // ">" + S_NOT = 76, // "!" + S_COMPLEMENT = 77, // "~" + S_ASSIGN = 78, // "=" + S_ASSIGN_ADD = 79, // "+=" + S_ASSIGN_SUB = 80, // "-=" + S_ASSIGN_MUL = 81, // "*=" + S_ASSIGN_DIV = 82, // "/=" + S_ASSIGN_MOD = 83, // "%=" + S_ASSIGN_BW_OR = 84, // "|=" + S_ASSIGN_BW_AND = 85, // "&=" + S_ASSIGN_BW_EXOR = 86, // "^=" + S_ASSIGN_RSHIFT = 87, // ">>=" + S_ASSIGN_LSHIFT = 88, // "<<=" + S_BITWISE_OR = 89, // "|" + S_BITWISE_AND = 90, // "&" + S_BITWISE_EXOR = 91, // "^" + S_ADD = 92, // "+" + S_SUB = 93, // "-" + S_MUL = 94, // "*" + S_DIV = 95, // "/" + S_MOD = 96, // "%" + S_PATH = 97, // "path" + S_IDENTIFIER = 98, // "identifier" + S_STRING = 99, // "string literal" + S_ISTRING = 100, // "localized string" + S_FLOAT = 101, // "float" + S_INTEGER = 102, // "integer" + S_SIZEOF = 103, // SIZEOF + S_ADD_ARRAY = 104, // ADD_ARRAY + S_THEN = 105, // THEN + S_TERN = 106, // TERN + S_NEG = 107, // NEG + S_ANIMREF = 108, // ANIMREF + S_PREINC = 109, // PREINC + S_PREDEC = 110, // PREDEC + S_POSTINC = 111, // POSTINC + S_POSTDEC = 112, // POSTDEC + S_YYACCEPT = 113, // $accept + S_root = 114, // root + S_program = 115, // program + S_inline = 116, // inline + S_include = 117, // include + S_declaration = 118, // declaration + S_decl_usingtree = 119, // decl_usingtree + S_decl_constant = 120, // decl_constant + S_decl_thread = 121, // decl_thread + S_stmt = 122, // stmt + S_stmt_or_dev = 123, // stmt_or_dev + S_stmt_list = 124, // stmt_list + S_stmt_or_dev_list = 125, // stmt_or_dev_list + S_stmt_dev = 126, // stmt_dev + S_stmt_block = 127, // stmt_block + S_stmt_expr = 128, // stmt_expr + S_stmt_call = 129, // stmt_call + S_stmt_assign = 130, // stmt_assign + S_stmt_endon = 131, // stmt_endon + S_stmt_notify = 132, // stmt_notify + S_stmt_wait = 133, // stmt_wait + S_stmt_waittill = 134, // stmt_waittill + S_stmt_waittillmatch = 135, // stmt_waittillmatch + S_stmt_waittillframeend = 136, // stmt_waittillframeend + S_stmt_waitframe = 137, // stmt_waitframe + S_stmt_if = 138, // stmt_if + S_stmt_ifelse = 139, // stmt_ifelse + S_stmt_while = 140, // stmt_while + S_stmt_dowhile = 141, // stmt_dowhile + S_stmt_for = 142, // stmt_for + S_stmt_foreach = 143, // stmt_foreach + S_stmt_switch = 144, // stmt_switch + S_stmt_case = 145, // stmt_case + S_stmt_default = 146, // stmt_default + S_stmt_break = 147, // stmt_break + S_stmt_continue = 148, // stmt_continue + S_stmt_return = 149, // stmt_return + S_stmt_breakpoint = 150, // stmt_breakpoint + S_stmt_prof_begin = 151, // stmt_prof_begin + S_stmt_prof_end = 152, // stmt_prof_end + S_expr = 153, // expr + S_expr_or_empty = 154, // expr_or_empty + S_expr_assign = 155, // expr_assign + S_expr_increment = 156, // expr_increment + S_expr_decrement = 157, // expr_decrement + S_expr_ternary = 158, // expr_ternary + S_expr_binary = 159, // expr_binary + S_expr_primitive = 160, // expr_primitive + S_expr_complement = 161, // expr_complement + S_expr_negate = 162, // expr_negate + S_expr_not = 163, // expr_not + S_expr_call = 164, // expr_call + S_expr_method = 165, // expr_method + S_expr_function = 166, // expr_function + S_expr_pointer = 167, // expr_pointer + S_expr_add_array = 168, // expr_add_array + S_expr_parameters = 169, // expr_parameters + S_expr_arguments = 170, // expr_arguments + S_expr_arguments_no_empty = 171, // expr_arguments_no_empty + S_expr_reference = 172, // expr_reference + S_expr_tuple = 173, // expr_tuple + S_expr_tuple_arguments = 174, // expr_tuple_arguments + S_expr_tuple_types = 175, // expr_tuple_types + S_expr_array = 176, // expr_array + S_expr_field = 177, // expr_field + S_expr_size = 178, // expr_size + S_expr_paren = 179, // expr_paren + S_expr_object = 180, // expr_object + S_expr_thisthread = 181, // expr_thisthread + S_expr_empty_array = 182, // expr_empty_array + S_expr_undefined = 183, // expr_undefined + S_expr_game = 184, // expr_game + S_expr_self = 185, // expr_self + S_expr_anim = 186, // expr_anim + S_expr_level = 187, // expr_level + S_expr_animation = 188, // expr_animation + S_expr_animtree = 189, // expr_animtree + S_expr_identifier_nosize = 190, // expr_identifier_nosize + S_expr_identifier = 191, // expr_identifier + S_expr_path = 192, // expr_path + S_expr_istring = 193, // expr_istring + S_expr_string = 194, // expr_string + S_expr_vector = 195, // expr_vector + S_expr_float = 196, // expr_float + S_expr_integer = 197, // expr_integer + S_expr_false = 198, // expr_false + S_expr_true = 199 // expr_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 () YY_NOEXCEPT + : 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (std::move (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (std::move (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< ast::stmt_waitframe::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (std::move (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (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, ast::call&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::call& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::decl&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::decl& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::decl_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 ast::decl_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, ast::decl_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 ast::decl_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, ast::decl_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 ast::decl_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, ast::expr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_add_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 ast::expr_add_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::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 ast::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, ast::expr_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 ast::expr_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, ast::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 ast::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, ast::expr_complement::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_complement::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_field::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_field::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_identifier::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_identifier::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_method::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_method::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_negate::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_negate::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_not::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_not::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_paren::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_paren::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_path::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_path::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_reference::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_reference::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_size::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_size::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_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, ast::expr_tuple::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::expr_tuple::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::expr_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 ast::expr_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, ast::expr_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 ast::expr_vector::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::stmt&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::stmt_breakpoint::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_breakpoint::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::stmt_dev::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_dev::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::stmt_dowhile::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_dowhile::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::stmt_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 ast::stmt_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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::stmt_prof_begin::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_prof_begin::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::stmt_prof_end::ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ast::stmt_prof_end::ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, ast::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 ast::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, 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 + + /// 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.template destroy< ast::call > (); + break; + + case symbol_kind::S_declaration: // declaration + value.template destroy< ast::decl > (); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.template destroy< ast::decl_constant::ptr > (); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.template destroy< ast::decl_thread::ptr > (); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.template destroy< ast::decl_usingtree::ptr > (); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.template destroy< ast::expr > (); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.template destroy< ast::expr_add_array::ptr > (); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.template destroy< ast::expr_anim::ptr > (); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.template destroy< ast::expr_animation::ptr > (); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.template destroy< ast::expr_animtree::ptr > (); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.template destroy< ast::expr_arguments::ptr > (); + break; + + case symbol_kind::S_expr_array: // expr_array + value.template destroy< ast::expr_array::ptr > (); + break; + + case symbol_kind::S_expr_call: // expr_call + value.template destroy< ast::expr_call::ptr > (); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.template destroy< ast::expr_complement::ptr > (); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.template destroy< ast::expr_empty_array::ptr > (); + break; + + case symbol_kind::S_expr_false: // expr_false + value.template destroy< ast::expr_false::ptr > (); + break; + + case symbol_kind::S_expr_field: // expr_field + value.template destroy< ast::expr_field::ptr > (); + break; + + case symbol_kind::S_expr_float: // expr_float + value.template destroy< ast::expr_float::ptr > (); + break; + + case symbol_kind::S_expr_game: // expr_game + value.template destroy< ast::expr_game::ptr > (); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.template destroy< ast::expr_identifier::ptr > (); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.template destroy< ast::expr_integer::ptr > (); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.template destroy< ast::expr_istring::ptr > (); + break; + + case symbol_kind::S_expr_level: // expr_level + value.template destroy< ast::expr_level::ptr > (); + break; + + case symbol_kind::S_expr_method: // expr_method + value.template destroy< ast::expr_method::ptr > (); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.template destroy< ast::expr_negate::ptr > (); + break; + + case symbol_kind::S_expr_not: // expr_not + value.template destroy< ast::expr_not::ptr > (); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.template destroy< ast::expr_parameters::ptr > (); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.template destroy< ast::expr_paren::ptr > (); + break; + + case symbol_kind::S_expr_path: // expr_path + value.template destroy< ast::expr_path::ptr > (); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.template destroy< ast::expr_reference::ptr > (); + break; + + case symbol_kind::S_expr_self: // expr_self + value.template destroy< ast::expr_self::ptr > (); + break; + + case symbol_kind::S_expr_size: // expr_size + value.template destroy< ast::expr_size::ptr > (); + break; + + case symbol_kind::S_expr_string: // expr_string + value.template destroy< ast::expr_string::ptr > (); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.template destroy< ast::expr_thisthread::ptr > (); + break; + + case symbol_kind::S_expr_true: // expr_true + value.template destroy< ast::expr_true::ptr > (); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.template destroy< ast::expr_tuple::ptr > (); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.template destroy< ast::expr_undefined::ptr > (); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.template destroy< ast::expr_vector::ptr > (); + break; + + case symbol_kind::S_include: // include + value.template destroy< ast::include::ptr > (); + break; + + case symbol_kind::S_program: // program + value.template destroy< ast::program::ptr > (); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.template destroy< ast::stmt > (); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.template destroy< ast::stmt_assign::ptr > (); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.template destroy< ast::stmt_break::ptr > (); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.template destroy< ast::stmt_breakpoint::ptr > (); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.template destroy< ast::stmt_call::ptr > (); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.template destroy< ast::stmt_case::ptr > (); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.template destroy< ast::stmt_continue::ptr > (); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.template destroy< ast::stmt_default::ptr > (); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.template destroy< ast::stmt_dev::ptr > (); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.template destroy< ast::stmt_dowhile::ptr > (); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.template destroy< ast::stmt_endon::ptr > (); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.template destroy< ast::stmt_expr::ptr > (); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.template destroy< ast::stmt_for::ptr > (); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.template destroy< ast::stmt_foreach::ptr > (); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.template destroy< ast::stmt_if::ptr > (); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.template destroy< ast::stmt_ifelse::ptr > (); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.template destroy< ast::stmt_list::ptr > (); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.template destroy< ast::stmt_notify::ptr > (); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.template destroy< ast::stmt_prof_begin::ptr > (); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.template destroy< ast::stmt_prof_end::ptr > (); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.template destroy< ast::stmt_return::ptr > (); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.template destroy< ast::stmt_switch::ptr > (); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.template destroy< ast::stmt_wait::ptr > (); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.template destroy< ast::stmt_waitframe::ptr > (); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.template destroy< ast::stmt_waittill::ptr > (); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.template destroy< ast::stmt_waittillframeend::ptr > (); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.template destroy< ast::stmt_waittillmatch::ptr > (); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.template destroy< ast::stmt_while::ptr > (); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.template destroy< std::string > (); + 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. + value_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 + { + /// The symbol kind as needed by the constructor. + typedef token_kind_type kind_type; + + /// Default constructor. + by_kind () YY_NOEXCEPT; + +#if 201103L <= YY_CPLUSPLUS + /// Move constructor. + by_kind (by_kind&& that) YY_NOEXCEPT; +#endif + + /// Copy constructor. + by_kind (const by_kind& that) YY_NOEXCEPT; + + /// Constructor from (external) token numbers. + by_kind (kind_type t) YY_NOEXCEPT; + + + + /// 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 () YY_NOEXCEPT {} + + /// Constructor for valueless symbols, and symbols from each type. +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, location_type l) + : super_type (token_kind_type (tok), std::move (l)) +#else + symbol_type (int tok, const location_type& l) + : super_type (token_kind_type (tok), l) +#endif + { +#if !defined _MSC_VER || defined __clang__ + S1C_ASSERT (tok == token::S1CEOF + || (token::S1Cerror <= tok && tok <= token::MOD) + || (token::SIZEOF <= tok && tok <= token::POSTDEC)); +#endif + } +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, std::string v, location_type l) + : super_type (token_kind_type (tok), std::move (v), std::move (l)) +#else + symbol_type (int tok, const std::string& v, const location_type& l) + : super_type (token_kind_type (tok), v, l) +#endif + { +#if !defined _MSC_VER || defined __clang__ + S1C_ASSERT ((token::PATH <= tok && tok <= token::INTEGER)); +#endif + } + }; + + /// Build a parser object. + parser (xsk::gsc::s1c::lexer& lexer_yyarg, xsk::gsc::ast::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 S1CDEBUG + /// 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 token kind. +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_S1CEOF (location_type l) + { + return symbol_type (token::S1CEOF, std::move (l)); + } +#else + static + symbol_type + make_S1CEOF (const location_type& l) + { + return symbol_type (token::S1CEOF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_S1Cerror (location_type l) + { + return symbol_type (token::S1Cerror, std::move (l)); + } +#else + static + symbol_type + make_S1Cerror (const location_type& l) + { + return symbol_type (token::S1Cerror, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_S1CUNDEF (location_type l) + { + return symbol_type (token::S1CUNDEF, std::move (l)); + } +#else + static + symbol_type + make_S1CUNDEF (const location_type& l) + { + return symbol_type (token::S1CUNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_DEFINE (location_type l) + { + return symbol_type (token::SH_DEFINE, std::move (l)); + } +#else + static + symbol_type + make_SH_DEFINE (const location_type& l) + { + return symbol_type (token::SH_DEFINE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_UNDEF (location_type l) + { + return symbol_type (token::SH_UNDEF, std::move (l)); + } +#else + static + symbol_type + make_SH_UNDEF (const location_type& l) + { + return symbol_type (token::SH_UNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_IFDEF (location_type l) + { + return symbol_type (token::SH_IFDEF, std::move (l)); + } +#else + static + symbol_type + make_SH_IFDEF (const location_type& l) + { + return symbol_type (token::SH_IFDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_IFNDEF (location_type l) + { + return symbol_type (token::SH_IFNDEF, std::move (l)); + } +#else + static + symbol_type + make_SH_IFNDEF (const location_type& l) + { + return symbol_type (token::SH_IFNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_IF (location_type l) + { + return symbol_type (token::SH_IF, std::move (l)); + } +#else + static + symbol_type + make_SH_IF (const location_type& l) + { + return symbol_type (token::SH_IF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_ELIF (location_type l) + { + return symbol_type (token::SH_ELIF, std::move (l)); + } +#else + static + symbol_type + make_SH_ELIF (const location_type& l) + { + return symbol_type (token::SH_ELIF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_ELSE (location_type l) + { + return symbol_type (token::SH_ELSE, std::move (l)); + } +#else + static + symbol_type + make_SH_ELSE (const location_type& l) + { + return symbol_type (token::SH_ELSE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SH_ENDIF (location_type l) + { + return symbol_type (token::SH_ENDIF, std::move (l)); + } +#else + static + symbol_type + make_SH_ENDIF (const location_type& l) + { + return symbol_type (token::SH_ENDIF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEVBEGIN (location_type l) + { + return symbol_type (token::DEVBEGIN, std::move (l)); + } +#else + static + symbol_type + make_DEVBEGIN (const location_type& l) + { + return symbol_type (token::DEVBEGIN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEVEND (location_type l) + { + return symbol_type (token::DEVEND, std::move (l)); + } +#else + static + symbol_type + make_DEVEND (const location_type& l) + { + return symbol_type (token::DEVEND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INLINE (location_type l) + { + return symbol_type (token::INLINE, std::move (l)); + } +#else + static + symbol_type + make_INLINE (const location_type& l) + { + return symbol_type (token::INLINE, 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_DO (location_type l) + { + return symbol_type (token::DO, std::move (l)); + } +#else + static + symbol_type + make_DO (const location_type& l) + { + return symbol_type (token::DO, 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_BREAKPOINT (location_type l) + { + return symbol_type (token::BREAKPOINT, std::move (l)); + } +#else + static + symbol_type + make_BREAKPOINT (const location_type& l) + { + return symbol_type (token::BREAKPOINT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PROFBEGIN (location_type l) + { + return symbol_type (token::PROFBEGIN, std::move (l)); + } +#else + static + symbol_type + make_PROFBEGIN (const location_type& l) + { + return symbol_type (token::PROFBEGIN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PROFEND (location_type l) + { + return symbol_type (token::PROFEND, std::move (l)); + } +#else + static + symbol_type + make_PROFEND (const location_type& l) + { + return symbol_type (token::PROFEND, 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_MUL (location_type l) + { + return symbol_type (token::ASSIGN_MUL, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_MUL (const location_type& l) + { + return symbol_type (token::ASSIGN_MUL, 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_BW_OR (location_type l) + { + return symbol_type (token::ASSIGN_BW_OR, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BW_OR (const location_type& l) + { + return symbol_type (token::ASSIGN_BW_OR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_BW_AND (location_type l) + { + return symbol_type (token::ASSIGN_BW_AND, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BW_AND (const location_type& l) + { + return symbol_type (token::ASSIGN_BW_AND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASSIGN_BW_EXOR (location_type l) + { + return symbol_type (token::ASSIGN_BW_EXOR, std::move (l)); + } +#else + static + symbol_type + make_ASSIGN_BW_EXOR (const location_type& l) + { + return symbol_type (token::ASSIGN_BW_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_MUL (location_type l) + { + return symbol_type (token::MUL, std::move (l)); + } +#else + static + symbol_type + make_MUL (const location_type& l) + { + return symbol_type (token::MUL, 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_PATH (std::string v, location_type l) + { + return symbol_type (token::PATH, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_PATH (const std::string& v, const location_type& l) + { + return symbol_type (token::PATH, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IDENTIFIER (std::string v, location_type l) + { + return symbol_type (token::IDENTIFIER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IDENTIFIER (const std::string& v, const location_type& l) + { + return symbol_type (token::IDENTIFIER, 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_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_INTEGER (std::string v, location_type l) + { + return symbol_type (token::INTEGER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INTEGER (const std::string& v, const location_type& l) + { + return symbol_type (token::INTEGER, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SIZEOF (location_type l) + { + return symbol_type (token::SIZEOF, std::move (l)); + } +#else + static + symbol_type + make_SIZEOF (const location_type& l) + { + return symbol_type (token::SIZEOF, 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) YY_NOEXCEPT; + + /// 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) YY_NOEXCEPT; + + 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_kind_type enum. + static symbol_kind_type yytranslate_ (int t) YY_NOEXCEPT; + + + + // 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 symbol kind of the accessing symbol of + // state STATE-NUM. + static const unsigned char yystos_[]; + + // YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. + static const unsigned char yyr1_[]; + + // YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. + static const signed char yyr2_[]; + + +#if S1CDEBUG + // 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) YY_NOEXCEPT + : 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) YY_NOEXCEPT + : 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) YY_NOEXCEPT; + + /// Constants. + enum + { + yylast_ = 2479, ///< Last index in yytable_. + yynnts_ = 87, ///< Number of nonterminal symbols. + yyfinal_ = 22 ///< Termination state number. + }; + + + // User arguments. + xsk::gsc::s1c::lexer& lexer; + xsk::gsc::ast::program::ptr& ast; + + }; + + inline + parser::symbol_kind_type + parser::yytranslate_ (int t) YY_NOEXCEPT + { + 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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.copy< ast::call > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.copy< ast::decl > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.copy< ast::decl_constant::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.copy< ast::decl_thread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.copy< ast::decl_usingtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.copy< ast::expr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.copy< ast::expr_add_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.copy< ast::expr_anim::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.copy< ast::expr_animation::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.copy< ast::expr_animtree::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.copy< ast::expr_arguments::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.copy< ast::expr_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.copy< ast::expr_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.copy< ast::expr_complement::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.copy< ast::expr_empty_array::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.copy< ast::expr_false::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.copy< ast::expr_field::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.copy< ast::expr_float::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.copy< ast::expr_game::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.copy< ast::expr_identifier::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.copy< ast::expr_integer::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.copy< ast::expr_istring::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.copy< ast::expr_level::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.copy< ast::expr_method::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.copy< ast::expr_negate::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.copy< ast::expr_not::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.copy< ast::expr_parameters::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.copy< ast::expr_paren::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.copy< ast::expr_path::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.copy< ast::expr_reference::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.copy< ast::expr_self::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.copy< ast::expr_size::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.copy< ast::expr_string::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.copy< ast::expr_thisthread::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.copy< ast::expr_true::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.copy< ast::expr_tuple::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.copy< ast::expr_undefined::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.copy< ast::expr_vector::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_include: // include + value.copy< ast::include::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_program: // program + value.copy< ast::program::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.copy< ast::stmt > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.copy< ast::stmt_assign::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.copy< ast::stmt_break::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.copy< ast::stmt_breakpoint::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.copy< ast::stmt_call::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.copy< ast::stmt_case::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.copy< ast::stmt_continue::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.copy< ast::stmt_default::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.copy< ast::stmt_dev::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.copy< ast::stmt_dowhile::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.copy< ast::stmt_endon::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.copy< ast::stmt_expr::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.copy< ast::stmt_for::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.copy< ast::stmt_foreach::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.copy< ast::stmt_if::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.copy< ast::stmt_ifelse::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.copy< ast::stmt_list::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.copy< ast::stmt_notify::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.copy< ast::stmt_prof_begin::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.copy< ast::stmt_prof_end::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.copy< ast::stmt_return::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.copy< ast::stmt_switch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.copy< ast::stmt_wait::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.copy< ast::stmt_waitframe::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.copy< ast::stmt_waittill::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.copy< ast::stmt_waittillframeend::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.copy< ast::stmt_waittillmatch::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.copy< ast::stmt_while::ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.copy< std::string > (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_expr_function: // expr_function + case symbol_kind::S_expr_pointer: // expr_pointer + value.move< ast::call > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_declaration: // declaration + value.move< ast::decl > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_decl_constant: // decl_constant + value.move< ast::decl_constant::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_decl_thread: // decl_thread + value.move< ast::decl_thread::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_decl_usingtree: // decl_usingtree + value.move< ast::decl_usingtree::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr: // expr + case symbol_kind::S_expr_or_empty: // expr_or_empty + case symbol_kind::S_expr_assign: // expr_assign + case symbol_kind::S_expr_increment: // expr_increment + case symbol_kind::S_expr_decrement: // expr_decrement + case symbol_kind::S_expr_ternary: // expr_ternary + case symbol_kind::S_expr_binary: // expr_binary + case symbol_kind::S_expr_primitive: // expr_primitive + case symbol_kind::S_expr_tuple: // expr_tuple + case symbol_kind::S_expr_tuple_types: // expr_tuple_types + case symbol_kind::S_expr_object: // expr_object + value.move< ast::expr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_add_array: // expr_add_array + value.move< ast::expr_add_array::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_anim: // expr_anim + value.move< ast::expr_anim::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_animation: // expr_animation + value.move< ast::expr_animation::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_animtree: // expr_animtree + value.move< ast::expr_animtree::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_arguments: // expr_arguments + case symbol_kind::S_expr_arguments_no_empty: // expr_arguments_no_empty + value.move< ast::expr_arguments::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_array: // expr_array + value.move< ast::expr_array::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_call: // expr_call + value.move< ast::expr_call::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_complement: // expr_complement + value.move< ast::expr_complement::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_empty_array: // expr_empty_array + value.move< ast::expr_empty_array::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_false: // expr_false + value.move< ast::expr_false::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_field: // expr_field + value.move< ast::expr_field::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_float: // expr_float + value.move< ast::expr_float::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_game: // expr_game + value.move< ast::expr_game::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_identifier_nosize: // expr_identifier_nosize + case symbol_kind::S_expr_identifier: // expr_identifier + value.move< ast::expr_identifier::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_integer: // expr_integer + value.move< ast::expr_integer::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_istring: // expr_istring + value.move< ast::expr_istring::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_level: // expr_level + value.move< ast::expr_level::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_method: // expr_method + value.move< ast::expr_method::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_negate: // expr_negate + value.move< ast::expr_negate::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_not: // expr_not + value.move< ast::expr_not::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_parameters: // expr_parameters + value.move< ast::expr_parameters::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_paren: // expr_paren + value.move< ast::expr_paren::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_path: // expr_path + value.move< ast::expr_path::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_reference: // expr_reference + value.move< ast::expr_reference::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_self: // expr_self + value.move< ast::expr_self::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_size: // expr_size + value.move< ast::expr_size::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_string: // expr_string + value.move< ast::expr_string::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_thisthread: // expr_thisthread + value.move< ast::expr_thisthread::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_true: // expr_true + value.move< ast::expr_true::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_tuple_arguments: // expr_tuple_arguments + value.move< ast::expr_tuple::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_undefined: // expr_undefined + value.move< ast::expr_undefined::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_expr_vector: // expr_vector + value.move< ast::expr_vector::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_include: // include + value.move< ast::include::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_program: // program + value.move< ast::program::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt: // stmt + case symbol_kind::S_stmt_or_dev: // stmt_or_dev + value.move< ast::stmt > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_assign: // stmt_assign + value.move< ast::stmt_assign::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_break: // stmt_break + value.move< ast::stmt_break::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_breakpoint: // stmt_breakpoint + value.move< ast::stmt_breakpoint::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_call: // stmt_call + value.move< ast::stmt_call::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_case: // stmt_case + value.move< ast::stmt_case::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_continue: // stmt_continue + value.move< ast::stmt_continue::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_default: // stmt_default + value.move< ast::stmt_default::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_dev: // stmt_dev + value.move< ast::stmt_dev::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_dowhile: // stmt_dowhile + value.move< ast::stmt_dowhile::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_endon: // stmt_endon + value.move< ast::stmt_endon::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_expr: // stmt_expr + value.move< ast::stmt_expr::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_for: // stmt_for + value.move< ast::stmt_for::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_foreach: // stmt_foreach + value.move< ast::stmt_foreach::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_if: // stmt_if + value.move< ast::stmt_if::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_ifelse: // stmt_ifelse + value.move< ast::stmt_ifelse::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_list: // stmt_list + case symbol_kind::S_stmt_or_dev_list: // stmt_or_dev_list + case symbol_kind::S_stmt_block: // stmt_block + value.move< ast::stmt_list::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_notify: // stmt_notify + value.move< ast::stmt_notify::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_prof_begin: // stmt_prof_begin + value.move< ast::stmt_prof_begin::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_prof_end: // stmt_prof_end + value.move< ast::stmt_prof_end::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_return: // stmt_return + value.move< ast::stmt_return::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_switch: // stmt_switch + value.move< ast::stmt_switch::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_wait: // stmt_wait + value.move< ast::stmt_wait::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waitframe: // stmt_waitframe + value.move< ast::stmt_waitframe::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittill: // stmt_waittill + value.move< ast::stmt_waittill::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittillframeend: // stmt_waittillframeend + value.move< ast::stmt_waittillframeend::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_waittillmatch: // stmt_waittillmatch + value.move< ast::stmt_waittillmatch::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_stmt_while: // stmt_while + value.move< ast::stmt_while::ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_PATH: // "path" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_STRING: // "string literal" + case symbol_kind::S_ISTRING: // "localized string" + case symbol_kind::S_FLOAT: // "float" + case symbol_kind::S_INTEGER: // "integer" + value.move< std::string > (YY_MOVE (s.value)); + break; + + default: + break; + } + + location = YY_MOVE (s.location); + } + + // by_kind. + inline + parser::by_kind::by_kind () YY_NOEXCEPT + : kind_ (symbol_kind::S_YYEMPTY) + {} + +#if 201103L <= YY_CPLUSPLUS + inline + parser::by_kind::by_kind (by_kind&& that) YY_NOEXCEPT + : kind_ (that.kind_) + { + that.clear (); + } +#endif + + inline + parser::by_kind::by_kind (const by_kind& that) YY_NOEXCEPT + : kind_ (that.kind_) + {} + + inline + parser::by_kind::by_kind (token_kind_type t) YY_NOEXCEPT + : 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::s1c +#line 5597 "parser.hpp" + + + + +#endif // !YY_S1C_PARSER_HPP_INCLUDED diff --git a/src/experimental/s1c/xsk/resolver.cpp b/src/experimental/s1c/xsk/resolver.cpp new file mode 100644 index 00000000..d8128306 --- /dev/null +++ b/src/experimental/s1c/xsk/resolver.cpp @@ -0,0 +1,517 @@ +// Copyright 2022 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 "s1c.hpp" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +#endif + +namespace xsk::gsc::s1c +{ + +std::unordered_map opcode_map; +std::unordered_map function_map; +std::unordered_map method_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 token_map_rev; +std::unordered_map> files; +read_cb_type read_callback = nullptr; +std::set string_map; + +void resolver::init(read_cb_type callback) +{ + read_callback = callback; +} + +void resolver::cleanup() +{ + files.clear(); +} + +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 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 std::string(itr->second); + } + + throw 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 +{ + if (name.starts_with("_func_")) + { + return static_cast(std::stoul(name.substr(6), nullptr, 16)); + } + + const auto itr = function_map_rev.find(name); + + if (itr != function_map_rev.end()) + { + return itr->second; + } + + throw 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 std::string(itr->second); + } + + return utils::string::va("_func_%04X", id); +} + +auto resolver::method_id(const std::string& name) -> std::uint16_t +{ + if (name.starts_with("_meth_")) + { + return static_cast(std::stoul(name.substr(6), nullptr, 16)); + } + + const auto itr = method_map_rev.find(name); + + if (itr != method_map_rev.end()) + { + return itr->second; + } + + throw 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 std::string(itr->second); + } + + return utils::string::va("_meth_%04X", id); +} + +auto resolver::token_id(const std::string& name) -> std::uint16_t +{ + if (name.starts_with("_id_")) + { + return static_cast(std::stoul(name.substr(4), nullptr, 16)); + } + + const auto itr = token_map_rev.find(name); + + if (itr != token_map_rev.end()) + { + return itr->second; + } + + return 0; +} + +auto resolver::token_name(std::uint16_t id) -> std::string +{ + const auto itr = token_map.find(id); + + if (itr != token_map.end()) + { + return std::string(itr->second); + } + + return utils::string::va("_id_%04X", id); +} + +auto resolver::find_function(const std::string& name) -> bool +{ + if (name.starts_with("_func_")) return true; + + 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 +{ + if (name.starts_with("_meth_")) return true; + + const auto itr = method_map_rev.find(name); + + if (itr != method_map_rev.end()) + { + return true; + } + + return false; +} + +void resolver::add_function(const std::string& name, std::uint16_t id) +{ + const auto itr = function_map_rev.find(name); + + if (itr != function_map_rev.end()) + { + throw error(utils::string::va("builtin function '%s' already defined.", name.data())); + } + + const auto str = string_map.find(name); + + if (str != string_map.end()) + { + function_map.insert({ id, *str }); + function_map_rev.insert({ *str, id }); + } + else + { + auto ins = string_map.insert(name); + + if (ins.second) + { + function_map.insert({ id, *ins.first }); + function_map_rev.insert({ *ins.first, id }); + } + } +} + +void resolver::add_method(const std::string& name, std::uint16_t id) +{ + const auto itr = method_map_rev.find(name); + + if (itr != method_map_rev.end()) + { + throw error(utils::string::va("builtin method '%s' already defined.", name.data())); + } + + const auto str = string_map.find(name); + + if (str != string_map.end()) + { + method_map.insert({ id, *str }); + method_map_rev.insert({ *str, id }); + } + else + { + auto ins = string_map.insert(name); + + if (ins.second) + { + method_map.insert({ id, *ins.first }); + method_map_rev.insert({ *ins.first, id }); + } + } +} + +auto resolver::make_token(std::string_view str) -> std::string +{ + if (str.starts_with("_id_") || str.starts_with("_func_") || str.starts_with("_meth_")) + { + return std::string(str); + } + + auto data = std::string(str.begin(), str.end()); + + for (std::size_t i = 0; i < data.size(); i++) + { + data[i] = static_cast(std::tolower(static_cast(str[i]))); + if (data[i] == '\\') data[i] = '/'; + } + + return data; +} + +auto resolver::file_data(const std::string& name) -> std::tuple +{ + const auto itr = files.find(name); + + if (itr != files.end()) + { + return { &itr->first ,reinterpret_cast(itr->second.data()), itr->second.size() }; + } + + auto data = read_callback(name); + + const auto res = files.insert({ name, std::move(data)}); + + if (res.second) + { + return { &res.first->first, reinterpret_cast(res.first->second.data()), res.first->second.size() }; + } + + throw error("couldn't open gsc file '" + name + "'"); +} + +std::set paths +{ +}; + +auto resolver::fs_to_game_path(const std::filesystem::path& file) -> std::filesystem::path +{ + auto result = std::filesystem::path(); + auto root = false; + + for (auto& entry : file) + { + if (!root && paths.contains(entry.string())) + { + result = entry; + root = true; + } + else if (paths.contains(result.string())) + { + result /= entry; + } + } + + return result.empty() ? file : result; +} + +const std::array, 154> opcode_list +{{ + { 0x1D, "OP_CastFieldObject" }, + { 0x1E, "OP_SetLocalVariableFieldCached" }, + { 0x1F, "OP_plus" }, + { 0x20, "OP_RemoveLocalVariables" }, + { 0x21, "OP_EvalSelfFieldVariableRef" }, + { 0x22, "OP_ScriptFarMethodChildThreadCall" }, + { 0x23, "OP_GetGameRef" }, + { 0x24, "OP_EvalAnimFieldVariable" }, + { 0x25, "OP_EvalLevelFieldVariableRef" }, + { 0x26, "OP_GetThisthread" }, + { 0x27, "OP_greater" }, + { 0x28, "OP_waittillmatch" }, + { 0x29, "OP_shift_right" }, + { 0x2A, "OP_dec" }, + { 0x2B, "OP_JumpOnTrue" }, + { 0x2C, "OP_bit_or" }, + { 0x2D, "OP_equality" }, + { 0x2E, "OP_ClearLocalVariableFieldCached0" }, + { 0x2F, "OP_notify" }, + { 0x30, "OP_GetVector" }, + { 0x31, "OP_ScriptMethodChildThreadCallPointer" }, + { 0x32, "OP_PreScriptCall" }, + { 0x33, "OP_GetByte" }, + { 0x34, "OP_ScriptFarMethodThreadCall" }, + { 0x35, "OP_SetSelfFieldVariableField" }, + { 0x36, "OP_JumpOnFalseExpr" }, + { 0x37, "OP_GetUndefined" }, + { 0x38, "OP_jumpback" }, + { 0x39, "OP_JumpOnTrueExpr" }, + { 0x3A, "OP_CallBuiltin0" }, + { 0x3B, "OP_CallBuiltin1" }, + { 0x3C, "OP_CallBuiltin2" }, + { 0x3D, "OP_CallBuiltin3" }, + { 0x3E, "OP_CallBuiltin4" }, + { 0x3F, "OP_CallBuiltin5" }, + { 0x40, "OP_CallBuiltin" }, + { 0x41, "OP_SetLocalVariableFieldCached0" }, + { 0x42, "OP_ClearFieldVariable" }, + { 0x43, "OP_GetLevel" }, + { 0x44, "OP_size" }, + { 0x45, "OP_SafeSetWaittillVariableFieldCached" }, + { 0x46, "OP_ScriptLocalThreadCall" }, + { 0x47, "OP_AddArray" }, + { 0x48, "OP_endon" }, + { 0x49, "OP_EvalFieldVariable" }, + { 0x4A, "OP_shift_left" }, + { 0x4B, "OP_EvalLocalArrayRefCached0" }, + { 0x4C, "OP_Return" }, + { 0x4D, "OP_CreateLocalVariable" }, + { 0x4E, "OP_SafeSetVariableFieldCached0" }, + { 0x4F, "OP_GetBuiltinFunction" }, + { 0x50, "OP_ScriptLocalMethodCall" }, + { 0x51, "OP_CallBuiltinMethodPointer" }, + { 0x52, "OP_ScriptLocalChildThreadCall" }, + { 0x53, "OP_GetSelfObject" }, + { 0x54, "OP_GetGame" }, + { 0x55, "OP_SetLevelFieldVariableField" }, + { 0x56, "OP_EvalArray" }, + { 0x57, "OP_GetSelf" }, + { 0x58, "OP_End" }, + { 0x59, "OP_EvalSelfFieldVariable" }, + { 0x5A, "OP_less_equal" }, + { 0x5B, "OP_EvalLocalVariableCached0" }, + { 0x5C, "OP_EvalLocalVariableCached1" }, + { 0x5D, "OP_EvalLocalVariableCached2" }, + { 0x5E, "OP_EvalLocalVariableCached3" }, + { 0x5F, "OP_EvalLocalVariableCached4" }, + { 0x60, "OP_EvalLocalVariableCached5" }, + { 0x61, "OP_EvalLocalVariableCached" }, + { 0x62, "OP_EvalNewLocalArrayRefCached0" }, + { 0x63, "OP_ScriptMethodChildThreadCallPointer" }, + { 0x64, "OP_EvalLocalVariableObjectCached" }, + { 0x65, "OP_ScriptLocalMethodThreadCall" }, + { 0x66, "OP_GetInteger" }, + { 0x67, "OP_ScriptMethodCallPointer" }, + { 0x68, "OP_checkclearparams" }, + { 0x69, "OP_SetAnimFieldVariableField" }, + { 0x6A, "OP_UNK_1" }, + { 0x6B, "OP_minus " }, + { 0x6C, "OP_ScriptLocalFunctionCall2" }, + { 0x6D, "OP_GetNegUnsignedShort" }, + { 0x6E, "OP_GetNegByte" }, + { 0x6F, "OP_SafeCreateVariableFieldCached" }, + { 0x70, "OP_greater_equal" }, + { 0x71, "OP_vector" }, + { 0x72, "OP_GetBuiltinMethod" }, + { 0x73, "OP_endswitch" }, + { 0x74, "OP_ClearArray" }, + { 0x75, "OP_DecTop" }, + { 0x76, "OP_CastBool" }, + { 0x77, "OP_EvalArrayRef" }, + { 0x78, "OP_SetNewLocalVariableFieldCached0" }, + { 0x79, "OP_GetZero" }, + { 0x7A, "OP_wait" }, + { 0x7B, "OP_waittill" }, + { 0x7C, "OP_GetIString" }, + { 0x7D, "OP_ScriptFarFunctionCall" }, + { 0x7E, "OP_GetAnimObject" }, + { 0x7F, "OP_GetAnimTree" }, + { 0x80, "OP_EvalLocalArrayCached" }, + { 0x81, "OP_mod" }, + { 0x82, "OP_ScriptFarThreadCall" }, + { 0x83, "OP_GetUnsignedShort" }, + { 0x84, "OP_clearparams" }, + { 0x85, "OP_ScriptMethodThreadCallPointer" }, + { 0x86, "OP_ScriptFunctionCallPointer" }, + { 0x87, "OP_EmptyArray" }, + { 0x88, "OP_SafeSetVariableFieldCached" }, + { 0x89, "OP_UNK_2" }, + { 0x8A, "OP_EvalFieldVariableRef" }, + { 0x8B, "OP_ScriptLocalMethodChildThreadCall" }, + { 0x8C, "OP_UNK_3" }, + { 0x8D, "OP_GetFloat" }, + { 0x8E, "OP_EvalLocalVariableRefCached" }, + { 0x8F, "OP_JumpOnFalse" }, + { 0x90, "OP_BoolComplement" }, + { 0x91, "OP_ScriptThreadCallPointer" }, + { 0x92, "OP_ScriptFarFunctionCall2" }, + { 0x93, "OP_less" }, + { 0x94, "OP_BoolNot" }, + { 0x95, "OP_waittillFrameEnd" }, + { 0x96, "OP_waitFrame" }, + { 0x97, "OP_GetString" }, + { 0x98, "OP_EvalLevelFieldVariable" }, + { 0x99, "OP_GetLevelObject" }, + { 0x9A, "OP_inc" }, + { 0x9B, "OP_CallBuiltinMethod0" }, + { 0x9C, "OP_CallBuiltinMethod1" }, + { 0x9D, "OP_CallBuiltinMethod2" }, + { 0x9E, "OP_CallBuiltinMethod3" }, + { 0x9F, "OP_CallBuiltinMethod4" }, + { 0xA0, "OP_CallBuiltinMethod5" }, + { 0xA1, "OP_CallBuiltinMethod" }, + { 0xA2, "OP_GetAnim" }, + { 0xA3, "OP_switch" }, + { 0xA4, "OP_SetVariableField" }, + { 0xA5, "OP_divide" }, + { 0xA6, "OP_GetLocalFunction" }, + { 0xA7, "OP_ScriptFarChildThreadCall" }, + { 0xA8, "OP_multiply" }, + { 0xA9, "OP_ClearLocalVariableFieldCached" }, + { 0xAA, "OP_EvalAnimFieldVariableRef" }, + { 0xAB, "OP_EvalLocalArrayRefCached" }, + { 0xAC, "OP_EvalLocalVariableRefCached0" }, + { 0xAD, "OP_bit_and" }, + { 0xAE, "OP_GetAnimation" }, + { 0xAF, "OP_GetFarFunction" }, + { 0xB0, "OP_CallBuiltinPointer" }, + { 0xB1, "OP_jump" }, + { 0xB2, "OP_voidCodepos" }, + { 0xB3, "OP_ScriptFarMethodCall" }, + { 0xB4, "OP_inequality" }, + { 0xB5, "OP_ScriptLocalFunctionCall" }, + { 0xB6, "OP_bit_ex_or" }, +}}; + +const std::array, 0> function_list +{{ +}}; + +const std::array, 0> method_list +{{ +}}; + +const std::array, 0> token_list +{{ +}}; + +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()); + token_map.reserve(token_list.size()); + token_map_rev.reserve(token_list.size()); + + for (const auto& entry : opcode_list) + { + opcode_map.insert({ entry.first, entry.second }); + opcode_map_rev.insert({ entry.second, entry.first }); + } + + for (const auto& entry : function_list) + { + function_map.insert({ entry.first, entry.second }); + function_map_rev.insert({ entry.second, entry.first }); + } + + for (const auto& entry : method_list) + { + method_map.insert({ entry.first, entry.second }); + method_map_rev.insert({ entry.second, entry.first }); + } + + for (const auto& entry : token_list) + { + token_map.insert({ entry.first, entry.second }); + token_map_rev.insert({ entry.second, entry.first }); + } + } +}; + +__init__ _; + +} // namespace xsk::gsc::s1c + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/src/experimental/s1c/xsk/resolver.hpp b/src/experimental/s1c/xsk/resolver.hpp new file mode 100644 index 00000000..9e5132f1 --- /dev/null +++ b/src/experimental/s1c/xsk/resolver.hpp @@ -0,0 +1,40 @@ +// Copyright 2022 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::s1c +{ + +class resolver +{ +public: + static void init(read_cb_type callback); + static void cleanup(); + + 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 token_id(const std::string& name) -> std::uint16_t; + static auto token_name(std::uint16_t id) -> std::string; + + static auto find_function(const std::string& name) -> bool; + static auto find_method(const std::string& name) -> bool; + + static void add_function(const std::string& name, std::uint16_t id); + static void add_method(const std::string& name, std::uint16_t id); + + static auto make_token(std::string_view str) -> std::string; + static auto file_data(const std::string& name) -> std::tuple; + static auto fs_to_game_path(const std::filesystem::path& file) -> std::filesystem::path; +}; + +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1_console/xsk/s1_console.cpp b/src/experimental/s1c/xsk/s1c.cpp similarity index 96% rename from src/experimental/s1_console/xsk/s1_console.cpp rename to src/experimental/s1c/xsk/s1c.cpp index f80475b1..8870bc01 100644 --- a/src/experimental/s1_console/xsk/s1_console.cpp +++ b/src/experimental/s1c/xsk/s1c.cpp @@ -4,14 +4,14 @@ // that can be found in the LICENSE file. #include "stdafx.hpp" -#include "s1_console.hpp" +#include "s1c.hpp" -namespace xsk::gsc::s1_console +namespace xsk::gsc::s1c { auto opcode_size(std::uint8_t id) -> std::uint32_t { - switch (opcode(id)) + switch (static_cast(id)) { case opcode::OP_End: case opcode::OP_Return: @@ -172,8 +172,8 @@ auto opcode_size(std::uint8_t id) -> std::uint32_t case opcode::OP_GetVector: return 13; default: - throw std::runtime_error("Couldn't resolve instruction size for " + std::to_string(id)); + throw error("couldn't resolve instruction size for " + std::to_string(id)); } } -} // namespace xsk::gsc::s1_console +} // namespace xsk::gsc::s1c diff --git a/src/experimental/s1_console/xsk/s1_console.hpp b/src/experimental/s1c/xsk/s1c.hpp similarity index 94% rename from src/experimental/s1_console/xsk/s1_console.hpp rename to src/experimental/s1c/xsk/s1c.hpp index dbddfc0e..99989b47 100644 --- a/src/experimental/s1_console/xsk/s1_console.hpp +++ b/src/experimental/s1c/xsk/s1c.hpp @@ -7,9 +7,18 @@ #include "utils/xsk/utils.hpp" -namespace xsk::gsc::s1_console +#include "assembler.hpp" +#include "disassembler.hpp" +#include "compiler.hpp" +#include "decompiler.hpp" +#include "resolver.hpp" +#include "context.hpp" + +namespace xsk::gsc::s1c { +constexpr std::uint16_t max_string_id = 0x0; + enum class opcode : std::uint8_t { OP_CastFieldObject = 0x1D, @@ -32,7 +41,7 @@ enum class opcode : std::uint8_t OP_ClearLocalVariableFieldCached0 = 0x2E, OP_notify = 0x2F, OP_GetVector = 0x30, - OP_ScriptMethodChildThreadCallPointer = 0x31, + OP_ScriptChildThreadCallPointer = 0x31, OP_PreScriptCall = 0x32, OP_GetByte = 0x33, OP_ScriptFarMethodThreadCall = 0x34, @@ -170,4 +179,4 @@ enum class opcode : std::uint8_t auto opcode_size(std::uint8_t id) -> std::uint32_t; -} // namespace xsk::gsc::s1_console +} // namespace xsk::gsc::s1c diff --git a/src/tool/xsk/main.cpp b/src/tool/xsk/main.cpp index 0467af3e..61f1ef1b 100644 --- a/src/tool/xsk/main.cpp +++ b/src/tool/xsk/main.cpp @@ -6,6 +6,8 @@ #include "stdafx.hpp" #include "utils/xsk/utils.hpp" #include "experimental/iw5c/xsk/iw5c.hpp" +#include "experimental/iw6c/xsk/iw6c.hpp" +#include "experimental/s1c/xsk/s1c.hpp" #include "iw5/xsk/iw5.hpp" #include "iw6/xsk/iw6.hpp" #include "iw7/xsk/iw7.hpp" @@ -22,7 +24,7 @@ namespace xsk enum class encd { _, source, assembly, binary }; enum class mode { _, assemble, disassemble, compile, decompile }; -enum class game { _, iw5c, iw5, iw6, iw7, iw8, s1, s2, s4, h1, h2, t6 }; +enum class game { _, iw5c, iw6c, s1c, iw5, iw6, iw7, iw8, s1, s2, s4, h1, h2, t6 }; const std::map exts = { @@ -43,6 +45,8 @@ const std::map modes = const std::map games = { { "iw5c", game::iw5c }, + { "iw6c", game::iw6c }, + { "s1c", game::s1c }, { "iw5", game::iw5 }, { "iw6", game::iw6 }, { "iw7", game::iw7 }, @@ -102,6 +106,10 @@ auto choose_resolver_file_name(uint32_t id, game& game) -> std::string { case game::iw5c: return iw5c::resolver::token_name(static_cast(id)); + case game::iw6c: + return iw6c::resolver::token_name(static_cast(id)); + case game::s1c: + return s1c::resolver::token_name(static_cast(id)); case game::iw5: return iw5::resolver::token_name(static_cast(id)); case game::iw6: @@ -406,6 +414,10 @@ void init() { contexts[game::iw5c] = std::make_unique(); contexts[game::iw5c]->init(build::prod, utils::file::read); + contexts[game::iw6c] = std::make_unique(); + contexts[game::iw6c]->init(build::prod, utils::file::read); + contexts[game::s1c] = std::make_unique(); + contexts[game::s1c]->init(build::prod, utils::file::read); contexts[game::iw5] = std::make_unique(); contexts[game::iw5]->init(build::prod, utils::file::read); contexts[game::iw6] = std::make_unique();