gsc-tool/gen/iw6/parser.ypp

678 lines
29 KiB
Plaintext

/* 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);
}