/* 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 {S1} %define api.namespace {xsk::gsc::s1} %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::s1::lexer& lexer } %parse-param { xsk::gsc::s1::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 "s1.hpp" namespace xsk::gsc::s1 { class lexer; } } %code top { #include "stdafx.hpp" #include "parser.hpp" #include "lexer.hpp" using namespace xsk::gsc; xsk::gsc::s1::parser::symbol_type S1lex(xsk::gsc::s1::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 <std::string> PATH "path" %token <std::string> IDENTIFIER "identifier" %token <std::string> STRING "string literal" %token <std::string> ISTRING "localized string" %token <std::string> FLOAT "float" %token <std::string> INTEGER "integer" %type <ast::program::ptr> program %type <ast::include::ptr> include %type <ast::decl> declaration %type <ast::decl_usingtree::ptr> decl_usingtree %type <ast::decl_constant::ptr> decl_constant %type <ast::decl_thread::ptr> decl_thread %type <ast::stmt> stmt %type <ast::stmt> stmt_or_dev %type <ast::stmt_list::ptr> stmt_list %type <ast::stmt_list::ptr> stmt_or_dev_list %type <ast::stmt_dev::ptr> stmt_dev %type <ast::stmt_list::ptr> stmt_block %type <ast::stmt_expr::ptr> stmt_expr %type <ast::stmt_call::ptr> stmt_call %type <ast::stmt_assign::ptr> stmt_assign %type <ast::stmt_endon::ptr> stmt_endon %type <ast::stmt_notify::ptr> stmt_notify %type <ast::stmt_wait::ptr> stmt_wait %type <ast::stmt_waittill::ptr> stmt_waittill %type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch %type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend %type <ast::stmt_waitframe::ptr> stmt_waitframe %type <ast::stmt_if::ptr> stmt_if %type <ast::stmt_ifelse::ptr> stmt_ifelse %type <ast::stmt_while::ptr> stmt_while %type <ast::stmt_dowhile::ptr> stmt_dowhile %type <ast::stmt_for::ptr> stmt_for %type <ast::stmt_foreach::ptr> stmt_foreach %type <ast::stmt_switch::ptr> stmt_switch %type <ast::stmt_case::ptr> stmt_case %type <ast::stmt_default::ptr> stmt_default %type <ast::stmt_break::ptr> stmt_break %type <ast::stmt_continue::ptr> stmt_continue %type <ast::stmt_return::ptr> stmt_return %type <ast::stmt_breakpoint::ptr> stmt_breakpoint %type <ast::stmt_prof_begin::ptr> stmt_prof_begin %type <ast::stmt_prof_end::ptr> stmt_prof_end %type <ast::expr> expr %type <ast::expr> expr_or_empty %type <ast::expr> expr_assign %type <ast::expr> expr_increment %type <ast::expr> expr_decrement %type <ast::expr> expr_ternary %type <ast::expr> expr_binary %type <ast::expr> expr_primitive %type <ast::expr_complement::ptr> expr_complement %type <ast::expr_negate::ptr> expr_negate %type <ast::expr_not::ptr> expr_not %type <ast::expr_call::ptr> expr_call %type <ast::expr_method::ptr> expr_method %type <ast::call> expr_function %type <ast::call> expr_pointer %type <ast::expr_add_array::ptr> expr_add_array %type <ast::expr_parameters::ptr> expr_parameters %type <ast::expr_arguments::ptr> expr_arguments %type <ast::expr_arguments::ptr> expr_arguments_no_empty %type <ast::expr_reference::ptr> expr_reference %type <ast::expr_array::ptr> expr_array %type <ast::expr_field::ptr> expr_field %type <ast::expr_size::ptr> expr_size %type <ast::expr_paren::ptr> expr_paren %type <ast::expr> expr_object %type <ast::expr_thisthread::ptr> expr_thisthread %type <ast::expr_empty_array::ptr> expr_empty_array %type <ast::expr_undefined::ptr> expr_undefined %type <ast::expr_game::ptr> expr_game %type <ast::expr_self::ptr> expr_self %type <ast::expr_anim::ptr> expr_anim %type <ast::expr_level::ptr> expr_level %type <ast::expr_animation::ptr> expr_animation %type <ast::expr_animtree::ptr> expr_animtree %type <ast::expr_identifier::ptr> expr_identifier_nosize %type <ast::expr_identifier::ptr> expr_identifier %type <ast::expr_path::ptr> expr_path %type <ast::expr_istring::ptr> expr_istring %type <ast::expr_string::ptr> expr_string %type <ast::expr_vector::ptr> expr_vector %type <ast::expr_float::ptr> expr_float %type <ast::expr_integer::ptr> expr_integer %type <ast::expr_false::ptr> expr_false %type <ast::expr_true::ptr> 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<ast::program>(@$); } ; 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<ast::program>(@$); } | include { $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); } | declaration { $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); } ; inline : INLINE expr_path SEMICOLON { lexer.push_header($2->value); } ; include : INCLUDE expr_path SEMICOLON { $$ = std::make_unique<ast::include>(@$, std::move($2)); } ; declaration : DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); } | DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); } | 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<ast::decl_usingtree>(@$, std::move($3)); } ; decl_constant : expr_identifier ASSIGN expr SEMICOLON { $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); } ; decl_thread : expr_identifier LPAREN expr_parameters RPAREN stmt_block { lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, 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<ast::stmt_list>(@$); $$->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<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); } ; stmt_dev : DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); } | DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); } ; stmt_block : LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); } | LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); } ; stmt_expr : expr_assign { $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); } | expr_increment { $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); } | expr_decrement { $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); } | { $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); } ; stmt_call : expr_call SEMICOLON { $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); } | expr_method SEMICOLON { $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); } ; stmt_assign : expr_assign SEMICOLON { $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); } | expr_increment SEMICOLON { $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); } | expr_decrement SEMICOLON { $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); } ; stmt_endon : expr_object ENDON LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); } ; stmt_notify : expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); } | expr_object NOTIFY LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); } ; stmt_wait : WAIT expr SEMICOLON { $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); } ; stmt_waittill : expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); } | expr_object WAITTILL LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); } ; stmt_waittillmatch : expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); } | expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); } ; stmt_waittillframeend : WAITTILLFRAMEEND SEMICOLON { $$ = std::make_unique<ast::stmt_waittillframeend>(@$); } ; stmt_waitframe : WAITFRAME SEMICOLON { $$ = std::make_unique<ast::stmt_waitframe>(@$); } | WAITFRAME LPAREN RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_waitframe>(@$); } ; stmt_if : IF LPAREN expr RPAREN stmt %prec THEN { $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); } ; stmt_ifelse : IF LPAREN expr RPAREN stmt ELSE stmt { $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); } ; stmt_while : WHILE LPAREN expr RPAREN stmt { $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); } ; stmt_dowhile : DO stmt WHILE LPAREN expr RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_dowhile>(@$, 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_for>(@$, 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::stmt_foreach>(@$, 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::stmt_foreach>(@$, 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<ast::stmt_switch>(@$, std::move($3), std::move($5)); } ; stmt_case : CASE expr_integer COLON { $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); } | CASE expr_string COLON { $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); } ; stmt_default : DEFAULT COLON { $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); } ; stmt_break : BREAK SEMICOLON { $$ = std::make_unique<ast::stmt_break>(@$); } ; stmt_continue : CONTINUE SEMICOLON { $$ = std::make_unique<ast::stmt_continue>(@$); } ; stmt_return : RETURN expr SEMICOLON { $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); } | RETURN SEMICOLON { $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); } ; stmt_breakpoint : BREAKPOINT SEMICOLON { $$ = std::make_unique<ast::stmt_breakpoint>(@$); } ; stmt_prof_begin : PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); } ; stmt_prof_end : PROFEND LPAREN expr_arguments RPAREN SEMICOLON { $$ = std::make_unique<ast::stmt_prof_end>(@$, 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<ast::node>(@$); } ; expr_assign : expr_object ASSIGN expr { $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_BW_OR expr { $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_BW_AND expr { $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_BW_EXOR expr { $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_LSHIFT expr { $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); } | expr_object ASSIGN_RSHIFT expr { $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_ADD expr { $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_SUB expr { $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_MUL expr { $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_DIV expr { $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); } | expr_object ASSIGN_MOD expr { $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); } ; expr_increment : INCREMENT expr_object %prec PREINC { $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); } | expr_object INCREMENT %prec POSTINC { $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); } ; expr_decrement : DECREMENT expr_object %prec PREDEC { $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); } | expr_object DECREMENT %prec POSTDEC { $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); } ; expr_ternary : expr QMARK expr COLON expr %prec TERN { $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); } ; expr_binary : expr OR expr { $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); } | expr AND expr { $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); } | expr EQUALITY expr { $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); } | expr INEQUALITY expr { $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); } | expr LESS_EQUAL expr { $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); } | expr GREATER_EQUAL expr { $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); } | expr LESS expr { $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); } | expr GREATER expr { $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); } | expr BITWISE_OR expr { $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); } | expr BITWISE_AND expr { $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); } | expr BITWISE_EXOR expr { $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); } | expr LSHIFT expr { $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); } | expr RSHIFT expr { $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); } | expr ADD expr { $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); } | expr SUB expr { $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); } | expr MUL expr { $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); } | expr DIV expr { $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); } | expr MOD expr { $$.as_node = std::make_unique<ast::expr_mod>(@$, 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<ast::expr_complement>(@$, std::move($2)); } ; expr_negate : SUB expr_identifier %prec NEG { $$ = std::make_unique<ast::expr_negate>(@$, ast::expr(std::move($2))); } | SUB expr_paren %prec NEG { $$ = std::make_unique<ast::expr_negate>(@$, ast::expr(std::move($2))); } | SUB expr_array %prec NEG { $$ = std::make_unique<ast::expr_negate>(@$, ast::expr(std::move($2))); } | SUB expr_field %prec NEG { $$ = std::make_unique<ast::expr_negate>(@$, ast::expr(std::move($2))); } ; expr_not : NOT expr { $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); } ; expr_call : expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); } | expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); } ; expr_method : expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); } | expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); } ; expr_function : expr_identifier LPAREN expr_arguments RPAREN { $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); } | expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN { $$.as_function = std::make_unique<ast::expr_function>(@$, 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<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), 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<ast::expr_function>(@$, 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<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), 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<ast::expr_function>(@$, 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<ast::expr_pointer>(@$, 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<ast::expr_pointer>(@$, 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<ast::expr_pointer>(@$, 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<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); } ; expr_add_array : LBRACKET expr_arguments_no_empty RBRACKET { $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); } ; expr_parameters : expr_parameters COMMA expr_identifier { $$ = std::move($1); $$->list.push_back(std::move($3)); } | expr_identifier { $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); } | { $$ = std::make_unique<ast::expr_parameters>(@$); } ; expr_arguments : expr_arguments_no_empty { $$ = std::move($1); } | { $$ = std::make_unique<ast::expr_arguments>(@$); } ; expr_arguments_no_empty : expr_arguments COMMA expr { $$ = std::move($1); $$->list.push_back(std::move($3)); } | expr %prec ADD_ARRAY { $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); } ; expr_reference : DOUBLECOLON expr_identifier { $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); } | expr_path DOUBLECOLON expr_identifier { $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); } ; expr_array : expr_object LBRACKET expr RBRACKET { $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); } ; expr_field : expr_object DOT expr_identifier_nosize { $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); } ; expr_size : expr_object DOT SIZE %prec SIZEOF { $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); } ; expr_paren : LPAREN expr RPAREN { $$ = std::make_unique<ast::expr_paren>(@$, 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<ast::expr_thisthread>(@$); }; ; expr_empty_array : LBRACKET RBRACKET { $$ = std::make_unique<ast::expr_empty_array>(@$); }; ; expr_undefined : UNDEFINED { $$ = std::make_unique<ast::expr_undefined>(@$); }; ; expr_game : GAME { $$ = std::make_unique<ast::expr_game>(@$); }; ; expr_self : SELF { $$ = std::make_unique<ast::expr_self>(@$); }; ; expr_anim : ANIM { $$ = std::make_unique<ast::expr_anim>(@$); }; ; expr_level : LEVEL { $$ = std::make_unique<ast::expr_level>(@$); }; ; expr_animation : MOD IDENTIFIER %prec ANIMREF { $$ = std::make_unique<ast::expr_animation>(@$, $2); }; ; expr_animtree : ANIMTREE { $$ = std::make_unique<ast::expr_animtree>(@$); }; ; expr_identifier_nosize : IDENTIFIER { $$ = std::make_unique<ast::expr_identifier>(@$, $1); }; ; expr_identifier : IDENTIFIER { $$ = std::make_unique<ast::expr_identifier>(@$, $1); }; | SIZE { $$ = std::make_unique<ast::expr_identifier>(@$, "size"); }; ; expr_path : IDENTIFIER { $$ = std::make_unique<ast::expr_path>(@$, $1); }; | PATH { $$ = std::make_unique<ast::expr_path>(@$, $1); }; ; expr_istring : ISTRING { $$ = std::make_unique<ast::expr_istring>(@$, $1); }; ; expr_string : STRING { $$ = std::make_unique<ast::expr_string>(@$, $1); }; ; expr_vector : LPAREN expr COMMA expr COMMA expr RPAREN { $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); }; ; expr_float : SUB FLOAT %prec NEG { $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); }; | FLOAT { $$ = std::make_unique<ast::expr_float>(@$, $1); }; ; expr_integer : SUB INTEGER %prec NEG { $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); }; | INTEGER { $$ = std::make_unique<ast::expr_integer>(@$, $1); }; ; expr_false : FALSE { $$ = std::make_unique<ast::expr_false>(@$); }; ; expr_true : TRUE { $$ = std::make_unique<ast::expr_true>(@$); }; ; %% void xsk::gsc::s1::parser::error(const xsk::gsc::location& loc, const std::string& msg) { throw xsk::gsc::comp_error(loc, msg); }