/* Copyright 2021 xensik. All rights reserved. // // Use of this source code is governed by a GNU GPLv3 license // that can be found in the LICENSE file. */ %require "3.7" %skeleton "lalr1.cc" %language "c++" %output "parser.cpp" %defines "parser.hpp" %define api.prefix {IW6} %define api.namespace {xsk::gsc::iw6} %define api.location.type {xsk::gsc::location} %define api.value.type variant %define api.token.constructor %define api.token.raw %define parse.assert %define parse.trace %define parse.error detailed %define parse.lac full %locations %lex-param { yyscan_t yyscanner } %lex-param { xsk::gsc::location& loc } %parse-param { yyscan_t yyscanner } %parse-param { xsk::gsc::location& loc } %parse-param { xsk::gsc::program_ptr& ast } %code requires { #include "iw6.hpp" typedef void *yyscan_t; #define YY_DECL xsk::gsc::iw6::parser::symbol_type IW6lex(yyscan_t yyscanner, xsk::gsc::location& loc) } %code top { #include "stdafx.hpp" #include "parser.hpp" #include "lexer.hpp" using namespace xsk::gsc; xsk::gsc::iw6::parser::symbol_type IW6lex(yyscan_t yyscanner, xsk::gsc::location& loc); } %token BREAKPOINT "breakpoint" %token PROFBEGIN "prof_begin" %token PROFEND "prof_end" %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 WHILE "while" %token FOR "for" %token FOREACH "foreach" %token IN "in" %token SWITCH "switch" %token CASE "case" %token DEFAULT "default" %token BREAK "break" %token CONTINUE "continue" %token RETURN "return" %token THREAD "thread" %token CHILDTHREAD "childthread" %token THISTHREAD "thisthread" %token CALL "call" %token TRUE "true" %token FALSE "false" %token UNDEFINED "undefined" %token SIZE ".size" %token GAME "game" %token SELF "self" %token ANIM "anim" %token LEVEL "level" %token LPAREN "(" %token RPAREN ")" %token LBRACE "{" %token RBRACE "}" %token LBRACKET "[" %token RBRACKET "]" %token COMMA "," %token DOT "." %token DOUBLECOLON "::" %token COLON ":" %token SEMICOLON ";" %token QMARK "?" %token INCREMENT "++" %token DECREMENT "--" %token LSHIFT "<<" %token RSHIFT ">>" %token OR "||" %token AND "&&" %token EQUALITY "==" %token INEQUALITY "!=" %token LESS_EQUAL "<=" %token GREATER_EQUAL ">=" %token LESS "<" %token GREATER ">" %token NOT "!" %token COMPLEMENT "~" %token ASSIGN "=" %token ASSIGN_ADD "+=" %token ASSIGN_SUB "-=" %token ASSIGN_MULT "*=" %token ASSIGN_DIV "/=" %token ASSIGN_MOD "%=" %token ASSIGN_BITWISE_OR "|=" %token ASSIGN_BITWISE_AND "&=" %token ASSIGN_BITWISE_EXOR "^=" %token ASSIGN_RSHIFT ">>=" %token ASSIGN_LSHIFT "<<=" %token BITWISE_OR "|" %token BITWISE_AND "&" %token BITWISE_EXOR "^" %token ADD "+" %token SUB "-" %token MULT "*" %token DIV "/" %token MOD "%" %token <std::string> FILE "file path" %token <std::string> NAME "identifier" %token <std::string> STRING "string literal" %token <std::string> ISTRING "localized string" %token <std::string> COLOR "color" %token <std::string> FLOAT "float" %token <std::string> INT_DEC "int" %token <std::string> INT_OCT "octal int" %token <std::string> INT_BIN "binary int" %token <std::string> INT_HEX "hexadecimal int" %type <program_ptr> program %type <include_ptr> include %type <define_ptr> define %type <usingtree_ptr> usingtree %type <constant_ptr> constant %type <thread_ptr> thread %type <parameters_ptr> parameters %type <stmt_ptr> stmt %type <stmt_list_ptr> stmt_block %type <stmt_list_ptr> stmt_list %type <stmt_call_ptr> stmt_call %type <stmt_assign_ptr> stmt_assign %type <stmt_endon_ptr> stmt_endon %type <stmt_notify_ptr> stmt_notify %type <stmt_wait_ptr> stmt_wait %type <stmt_waittill_ptr> stmt_waittill %type <stmt_waittillmatch_ptr> stmt_waittillmatch %type <stmt_waittillframeend_ptr> stmt_waittillframeend %type <stmt_if_ptr> stmt_if %type <stmt_ifelse_ptr> stmt_ifelse %type <stmt_while_ptr> stmt_while %type <stmt_for_ptr> stmt_for %type <stmt_foreach_ptr> stmt_foreach %type <stmt_switch_ptr> stmt_switch %type <stmt_case_ptr> stmt_case %type <stmt_default_ptr> stmt_default %type <stmt_break_ptr> stmt_break %type <stmt_continue_ptr> stmt_continue %type <stmt_return_ptr> stmt_return %type <stmt_breakpoint_ptr> stmt_breakpoint %type <stmt_prof_begin_ptr> stmt_prof_begin %type <stmt_prof_end_ptr> stmt_prof_end %type <stmt_ptr> for_stmt %type <expr_ptr> for_expr %type <expr_assign_ptr> expr_assign %type <expr_ptr> expr %type <expr_ptr> expr_compare %type <expr_ptr> expr_ternary %type <expr_ptr> expr_binary %type <expr_ptr> expr_primitive %type <expr_call_ptr> expr_call %type <expr_call_ptr> expr_call_thread %type <expr_call_ptr> expr_call_childthread %type <expr_call_type_ptr> expr_call_function %type <expr_call_type_ptr> expr_call_pointer %type <expr_arguments_ptr> expr_arguments %type <expr_arguments_ptr> expr_arguments_filled %type <expr_arguments_ptr> expr_arguments_empty %type <node_ptr> expr_function %type <node_ptr> expr_add_array %type <node_ptr> expr_array %type <node_ptr> expr_field %type <node_ptr> expr_size %type <node_ptr> object %type <thisthread_ptr> thisthread %type <empty_array_ptr> empty_array %type <undefined_ptr> undefined %type <game_ptr> game %type <self_ptr> self %type <anim_ptr> anim %type <level_ptr> level %type <animation_ptr> animation %type <animtree_ptr> animtree %type <name_ptr> name %type <file_ptr> file %type <istring_ptr> istring %type <string_ptr> string %type <color_ptr> color %type <vector_ptr> vector %type <float_ptr> float %type <integer_ptr> integer %type <false_ptr> false %type <true_ptr> true %nonassoc ADD_ARRAY %nonassoc RBRACKET %nonassoc THEN %nonassoc ELSE %nonassoc INCREMENT DECREMENT %precedence TERN %right QMARK %left OR %left AND %left BITWISE_OR %left BITWISE_EXOR %left BITWISE_AND %left EQUALITY INEQUALITY %left LESS GREATER LESS_EQUAL GREATER_EQUAL %left LSHIFT RSHIFT %left ADD SUB %left MULT DIV MOD %right NOT COMPLEMENT %precedence NEG %precedence ANIMREF %precedence PREINC PREDEC %precedence POSTINC POSTDEC %start root %% root : program { ast = std::move($1); } | { ast = std::make_unique<node_program>(@$); } ; program : program include { $$ = std::move($1); $$->includes.push_back(std::move($2)); } | program define { $$ = std::move($1); $$->definitions.push_back(std::move($2)); } | include { $$ = std::make_unique<node_program>(@$); $$->includes.push_back(std::move($1)); } | define { $$ = std::make_unique<node_program>(@$); $$->definitions.push_back(std::move($1)); } ; include : INCLUDE file SEMICOLON { $$ = std::make_unique<node_include>(@$, std::move($2)); } ; define : usingtree { $$.as_usingtree = std::move($1); } | constant { $$.as_constant = std::move($1); } | thread { $$.as_thread = std::move($1); } ; usingtree : USINGTREE LPAREN string RPAREN SEMICOLON { $$ = std::make_unique<node_usingtree>(@$, std::move($3)); } ; constant : name ASSIGN expr SEMICOLON { $$ = std::make_unique<node_constant>(@$, std::move($1), std::move($3)); } ; thread : name LPAREN parameters RPAREN stmt_block { $$ = std::make_unique<node_thread>(@$, std::move($1), std::move($3), std::move($5)); } ; parameters : parameters COMMA name { $$ = std::move($1); $$->list.push_back(std::move($3)); } | name { $$ = std::make_unique<node_parameters>(@$); $$->list.push_back(std::move($1)); } | { $$ = std::make_unique<node_parameters>(@$); } ; 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_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_block : LBRACE stmt_list RBRACE { $$ = std::move($2); } | LBRACE RBRACE { $$ = std::make_unique<node_stmt_list>(@$); } ; stmt_list : stmt_list stmt { $$ = std::move($1); $$->stmts.push_back(std::move($2)); } | stmt { $$ = std::make_unique<node_stmt_list>(@$); $$->stmts.push_back(std::move($1)); } ; stmt_call : expr_call SEMICOLON { $$ = std::make_unique<node_stmt_call>(@$, std::move($1)); } | expr_call_thread SEMICOLON { $$ = std::make_unique<node_stmt_call>(@$, std::move($1)); } ; stmt_assign : expr_assign SEMICOLON { $$ = std::make_unique<node_stmt_assign>(@$, std::move($1)); } ; stmt_endon : object ENDON LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_endon>(@$, std::move($1), std::move($4)); } ; stmt_notify : object NOTIFY LPAREN expr COMMA expr_arguments RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); } | object NOTIFY LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<node_expr_arguments>(@$)); } ; stmt_wait : WAIT expr SEMICOLON { $$ = std::make_unique<node_stmt_wait>(@$, std::move($2)); } ; stmt_waittill : object WAITTILL LPAREN expr COMMA expr_arguments RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); } | object WAITTILL LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<node_expr_arguments>(@$)); } ; stmt_waittillmatch : object WAITTILLMATCH LPAREN expr COMMA expr_arguments RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); } | object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<node_expr_arguments>(@$)); } ; stmt_waittillframeend : WAITTILLFRAMEEND SEMICOLON { $$ = std::make_unique<node_stmt_waittillframeend>(@$); } ; stmt_if : IF LPAREN expr RPAREN stmt %prec THEN { $$ = std::make_unique<node_stmt_if>(@$, std::move($3), std::move($5)); } ; stmt_ifelse : IF LPAREN expr RPAREN stmt ELSE stmt { $$ = std::make_unique<node_stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); } ; stmt_while : WHILE LPAREN expr RPAREN stmt { $$ = std::make_unique<node_stmt_while>(@$, std::move($3), std::move($5)); } ; stmt_for : FOR LPAREN for_stmt SEMICOLON for_expr SEMICOLON for_stmt RPAREN stmt { $$ = std::make_unique<node_stmt_for>(@$, std::move($3), std::move($5), std::move($7), std::move($9)); } ; stmt_foreach : FOREACH LPAREN name IN expr RPAREN stmt { $$ = std::make_unique<node_stmt_foreach>(@$, expr_ptr(std::move($3)), std::move($5), std::move($7)); } | FOREACH LPAREN name COMMA name IN expr RPAREN stmt { $$ = std::make_unique<node_stmt_foreach>(@$, expr_ptr(std::move($3)), expr_ptr(std::move($5)), std::move($7), std::move($9)); } ; stmt_switch : SWITCH LPAREN expr RPAREN stmt_block { $$ = std::make_unique<node_stmt_switch>(@$, std::move($3), std::move($5)); } ; stmt_case : CASE integer COLON { $$ = std::make_unique<node_stmt_case>(@$, expr_ptr(std::move($2)), std::make_unique<gsc::node_stmt_list>(@$)); } | CASE string COLON { $$ = std::make_unique<node_stmt_case>(@$, expr_ptr(std::move($2)), std::make_unique<gsc::node_stmt_list>(@$)); } ; stmt_default : DEFAULT COLON { $$ = std::make_unique<node_stmt_default>(@$, std::make_unique<gsc::node_stmt_list>(@$)); } ; stmt_break : BREAK SEMICOLON { $$ = std::make_unique<node_stmt_break>(@$); } ; stmt_continue : CONTINUE SEMICOLON { $$ = std::make_unique<node_stmt_continue>(@$); } ; stmt_return : RETURN expr SEMICOLON { $$ = std::make_unique<node_stmt_return>(@$, std::move($2)); } | RETURN SEMICOLON { $$ = std::make_unique<node_stmt_return>(@$, std::make_unique<node>(@$)); } ; stmt_breakpoint : BREAKPOINT SEMICOLON { $$ = std::make_unique<node_stmt_breakpoint>(@$); } ; stmt_prof_begin : PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_prof_begin>(@$, std::move($3)); } ; stmt_prof_end : PROFEND LPAREN expr_arguments RPAREN SEMICOLON { $$ = std::make_unique<node_stmt_prof_end>(@$, std::move($3)); } ; for_stmt : expr_assign { $$.as_list = std::make_unique<node_stmt_list>(@$); $$.as_list->stmts.push_back(stmt_ptr(std::make_unique<node_stmt_assign>(@$, std::move($1)))); } | { $$.as_node = std::make_unique<node>(@$); } ; for_expr : expr { $$ = std::move($1); } | { $$.as_node = std::make_unique<node>(@$); } ; expr : expr_compare { $$ = std::move($1); } | expr_ternary { $$ = std::move($1); } | expr_binary { $$ = std::move($1); } | expr_primitive { $$ = std::move($1); } ; expr_assign : INCREMENT object %prec PREINC { $$ = std::make_unique<node_expr_increment>(@$, std::move($2)); } | DECREMENT object %prec PREDEC { $$ = std::make_unique<node_expr_decrement>(@$, std::move($2)); } | object INCREMENT %prec POSTINC { $$ = std::make_unique<node_expr_increment>(@$, std::move($1)); } | object DECREMENT %prec POSTDEC { $$ = std::make_unique<node_expr_decrement>(@$, std::move($1)); } | object ASSIGN expr { $$ = std::make_unique<node_expr_assign_equal>(@$, std::move($1), std::move($3)); } | object ASSIGN_BITWISE_OR expr { $$ = std::make_unique<node_expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); } | object ASSIGN_BITWISE_AND expr { $$ = std::make_unique<node_expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); } | object ASSIGN_BITWISE_EXOR expr { $$ = std::make_unique<node_expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); } | object ASSIGN_LSHIFT expr { $$ = std::make_unique<node_expr_assign_shift_left>(@$, std::move($1),std::move( $3)); } | object ASSIGN_RSHIFT expr { $$ = std::make_unique<node_expr_assign_shift_right>(@$, std::move($1), std::move($3)); } | object ASSIGN_ADD expr { $$ = std::make_unique<node_expr_assign_add>(@$, std::move($1), std::move($3)); } | object ASSIGN_SUB expr { $$ = std::make_unique<node_expr_assign_sub>(@$, std::move($1), std::move($3)); } | object ASSIGN_MULT expr { $$ = std::make_unique<node_expr_assign_mult>(@$, std::move($1), std::move($3)); } | object ASSIGN_DIV expr { $$ = std::make_unique<node_expr_assign_div>(@$, std::move($1), std::move($3)); } | object ASSIGN_MOD expr { $$ = std::make_unique<node_expr_assign_mod>(@$, std::move($1), std::move($3)); } ; expr_compare : expr OR expr { $$.as_node = std::make_unique<node_expr_or>(@$, std::move($1), std::move($3)); } | expr AND expr { $$.as_node = std::make_unique<node_expr_and>(@$, std::move($1), std::move($3)); } | expr EQUALITY expr { $$.as_node = std::make_unique<node_expr_equality>(@$, std::move($1), std::move($3)); } | expr INEQUALITY expr { $$.as_node = std::make_unique<node_expr_inequality>(@$, std::move($1), std::move($3)); } | expr LESS_EQUAL expr { $$.as_node = std::make_unique<node_expr_less_equal>(@$, std::move($1), std::move($3)); } | expr GREATER_EQUAL expr { $$.as_node = std::make_unique<node_expr_greater_equal>(@$, std::move($1), std::move($3)); } | expr LESS expr { $$.as_node = std::make_unique<node_expr_less>(@$, std::move($1), std::move($3)); } | expr GREATER expr { $$.as_node = std::make_unique<node_expr_greater>(@$, std::move($1), std::move($3)); } ; expr_ternary : expr QMARK expr COLON expr %prec TERN { $$.as_node = std::make_unique<node_expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); } ; expr_binary : expr BITWISE_OR expr { $$.as_node = std::make_unique<node_expr_bitwise_or>(@$, std::move($1), std::move($3)); } | expr BITWISE_AND expr { $$.as_node = std::make_unique<node_expr_bitwise_and>(@$, std::move($1), std::move($3)); } | expr BITWISE_EXOR expr { $$.as_node = std::make_unique<node_expr_bitwise_exor>(@$, std::move($1), std::move($3)); } | expr LSHIFT expr { $$.as_node = std::make_unique<node_expr_shift_left>(@$, std::move($1), std::move($3)); } | expr RSHIFT expr { $$.as_node = std::make_unique<node_expr_shift_right>(@$, std::move($1), std::move($3)); } | expr ADD expr { $$.as_node = std::make_unique<node_expr_add>(@$, std::move($1), std::move($3)); } | expr SUB expr { $$.as_node = std::make_unique<node_expr_sub>(@$, std::move($1), std::move($3)); } | expr MULT expr { $$.as_node = std::make_unique<node_expr_mult>(@$, std::move($1), std::move($3)); } | expr DIV expr { $$.as_node = std::make_unique<node_expr_div>(@$, std::move($1), std::move($3)); } | expr MOD expr { $$.as_node = std::make_unique<node_expr_mod>(@$, std::move($1), std::move($3)); } ; expr_primitive : LPAREN expr RPAREN { $$ = std::move($2); } | COMPLEMENT expr { $$.as_node = std::make_unique<node_expr_complement>(@$, std::move($2)); } | NOT expr { $$.as_node = std::make_unique<node_expr_not>(@$, std::move($2)); } | expr_call { $$.as_node = std::move($1); } | expr_call_thread { $$.as_node = std::move($1); } | expr_call_childthread { $$.as_node = std::move($1); } | expr_function { $$.as_node = std::move($1); } | expr_add_array { $$.as_node = std::move($1); } | expr_array { $$.as_node = std::move($1); } | expr_field { $$.as_node = std::move($1); } | expr_size { $$.as_node = std::move($1); } | thisthread { $$.as_node = std::move($1); } | empty_array { $$.as_node = std::move($1); } | undefined { $$.as_node = std::move($1); } | game { $$.as_node = std::move($1); } | self { $$.as_node = std::move($1); } | anim { $$.as_node = std::move($1); } | level { $$.as_node = std::move($1); } | animation { $$.as_node = std::move($1); } | animtree { $$.as_node = std::move($1); } | name { $$.as_node = std::move($1); } | istring { $$.as_node = std::move($1); } | string { $$.as_node = std::move($1); } | color { $$.as_node = std::move($1); } | vector { $$.as_node = std::move($1); } | float { $$.as_node = std::move($1); } | integer { $$.as_node = std::move($1); } | false { $$.as_node = std::move($1); } | true { $$.as_node = std::move($1); } ; expr_call : expr_call_function { $$ = std::make_unique<node_expr_call>(@$, false, false, std::make_unique<node>(@$), std::move($1)); } | expr_call_pointer { $$ = std::make_unique<node_expr_call>(@$, false, false, std::make_unique<node>(@$), std::move($1)); } | object expr_call_function { $$ = std::make_unique<node_expr_call>(@$, false, false, std::move($1), std::move($2)); } | object expr_call_pointer { $$ = std::make_unique<node_expr_call>(@$, false, false, std::move($1), std::move($2)); } ; expr_call_thread : THREAD expr_call_function { $$ = std::make_unique<node_expr_call>(@$, true, false, std::make_unique<node>(@$), std::move($2)); } | THREAD expr_call_pointer { $$ = std::make_unique<node_expr_call>(@$, true, false, std::make_unique<node>(@$), std::move($2)); } | object THREAD expr_call_function { $$ = std::make_unique<node_expr_call>(@$, true, false, std::move($1), std::move($3)); } | object THREAD expr_call_pointer { $$ = std::make_unique<node_expr_call>(@$, true, false, std::move($1), std::move($3)); } ; expr_call_childthread : CHILDTHREAD expr_call_function { $$ = std::make_unique<node_expr_call>(@$, false, true, std::make_unique<node>(@$), std::move($2)); } | CHILDTHREAD expr_call_pointer { $$ = std::make_unique<node_expr_call>(@$, false, true, std::make_unique<node>(@$), std::move($2)); } | object CHILDTHREAD expr_call_function { $$ = std::make_unique<node_expr_call>(@$, false, true, std::move($1), std::move($3)); } | object CHILDTHREAD expr_call_pointer { $$ = std::make_unique<node_expr_call>(@$, false, true, std::move($1), std::move($3)); } ; expr_call_function : name LPAREN expr_arguments RPAREN {$$.as_func = std::make_unique<node_expr_call_function>(@$, std::make_unique<node_file>(), std::move($1), std::move($3)); } | file DOUBLECOLON name LPAREN expr_arguments RPAREN { $$.as_func = std::make_unique<node_expr_call_function>(@$, std::move($1), std::move($3), std::move($5)); } ; expr_call_pointer : LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN { $$.as_pointer = std::make_unique<node_expr_call_pointer>(@$, false, std::move($3), std::move($7)); } | CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN { $$.as_pointer = std::make_unique<node_expr_call_pointer>(@$, true, std::move($4), std::move($8)); } ; expr_arguments : expr_arguments_filled { $$ = std::move($1); } | expr_arguments_empty { $$ = std::move($1); } ; expr_arguments_filled : expr_arguments COMMA expr { $$ = std::move($1); $$->list.push_back(std::move($3)); } | expr %prec ADD_ARRAY { $$ = std::make_unique<node_expr_arguments>(@$); $$->list.push_back(std::move($1)); } ; expr_arguments_empty : { $$ = std::make_unique<node_expr_arguments>(@$); } ; expr_function : DOUBLECOLON name { $$ = std::make_unique<node_expr_function>(@$, std::make_unique<node_file>(@$), std::move($2)); } | file DOUBLECOLON name { $$ = std::make_unique<node_expr_function>(@$, std::move($1), std::move($3)); } ; expr_add_array : LBRACKET expr_arguments_filled RBRACKET { $$ = std::make_unique<node_expr_add_array>(@$, std::move($2)); } ; expr_array : object LBRACKET expr RBRACKET { $$ = std::make_unique<node_expr_array>(@$, std::move($1), std::move($3)); } ; expr_field : object DOT name { $$ = std::make_unique<node_expr_field>(@$, std::move($1), std::move($3)); } ; expr_size : object SIZE { $$ = std::make_unique<node_expr_size>(@$, std::move($1)); } ; object : expr_call { $$ = std::move($1); } | expr_array { $$ = std::move($1); } | expr_field { $$ = std::move($1); } | game { $$ = std::move($1); } | self { $$ = std::move($1); } | anim { $$ = std::move($1); } | level { $$ = std::move($1); } | name { $$ = std::move($1); } ; float : SUB FLOAT %prec NEG { $$ = std::make_unique<node_float>(@$, "-" + $2); }; | FLOAT { $$ = std::make_unique<node_float>(@$, $1); }; ; integer : SUB INT_DEC %prec NEG { $$ = std::make_unique<node_integer>(@$, "-" + $2); }; | INT_DEC { $$ = std::make_unique<node_integer>(@$, $1); }; | INT_OCT { $$ = std::make_unique<node_integer>(@$, $1); }; | INT_BIN { $$ = std::make_unique<node_integer>(@$, $1); }; | INT_HEX { $$ = std::make_unique<node_integer>(@$, $1); }; ; thisthread : THISTHREAD { $$ = std::make_unique<node_thisthread>(@$); }; empty_array : LBRACKET RBRACKET { $$ = std::make_unique<node_empty_array>(@$); }; undefined : UNDEFINED { $$ = std::make_unique<node_undefined>(@$); }; game : GAME { $$ = std::make_unique<node_game>(@$); }; self : SELF { $$ = std::make_unique<node_self>(@$); }; anim : ANIM { $$ = std::make_unique<node_anim>(@$); }; level : LEVEL { $$ = std::make_unique<node_level>(@$); }; animation : MOD NAME %prec ANIMREF { $$ = std::make_unique<node_animation>(@$, $2); }; animtree : ANIMTREE { $$ = std::make_unique<node_animtree>(@$); }; name : NAME { $$ = std::make_unique<node_name>(@$, $1); }; file : FILE { $$ = std::make_unique<node_file>(@$, $1); }; istring : ISTRING { $$ = std::make_unique<node_istring>(@$, $1); }; string : STRING { $$ = std::make_unique<node_string>(@$, $1); }; color : COLOR { $$ = std::make_unique<node_color>(@$, $1); }; vector : LPAREN expr COMMA expr COMMA expr RPAREN { $$ = std::make_unique<node_vector>(@$, std::move($2), std::move($4), std::move($6)); }; false : FALSE { $$ = std::make_unique<node_false>(@$); }; true : TRUE { $$ = std::make_unique<node_true>(@$); }; %% void xsk::gsc::iw6::parser::error(const xsk::gsc::location& loc, const std::string& msg) { throw xsk::gsc::comp_error(loc, msg); }