feature(preprocessor): implement preprocessor & parse command (#48)
This commit is contained in:
parent
e4e884d110
commit
bc0cc6d0f5
@ -26,7 +26,7 @@ A utility to compile & decompile IW engine game scripts.
|
|||||||
## Usage
|
## Usage
|
||||||
``./gsc-tool.exe <mode> <game> <path>``
|
``./gsc-tool.exe <mode> <game> <path>``
|
||||||
|
|
||||||
**modes**: `asm`, `disasm`, `comp`, `decomp`
|
**modes**: `asm`, `disasm`, `comp`, `decomp`, `parse`
|
||||||
- *note:* zonetool files (*.cgsc*, *.cgsc.stack*) use: `zasm`, `zdisasm`, `zcomp`, `zdecomp` modes
|
- *note:* zonetool files (*.cgsc*, *.cgsc.stack*) use: `zasm`, `zdisasm`, `zcomp`, `zdecomp` modes
|
||||||
|
|
||||||
**games**: `iw5`, `iw6`, `iw7`, `iw8`, `iw9`, `s1`, `s2`, `s4`, `h1`, `h2`, `t6`
|
**games**: `iw5`, `iw6`, `iw7`, `iw8`, `iw9`, `s1`, `s2`, `s4`, `h1`, `h2`, `t6`
|
||||||
@ -42,6 +42,7 @@ Example: ``./gsc-tool.exe comp iw5 ./data/iw5/my_fancy_script.gsc``
|
|||||||
|`disasm` |dissasemble a `file.gscbin`|`file.gscasm`|
|
|`disasm` |dissasemble a `file.gscbin`|`file.gscasm`|
|
||||||
|`comp` |compile a `file.gsc` |`file.gscbin`|
|
|`comp` |compile a `file.gsc` |`file.gscbin`|
|
||||||
|`decomp` |decompile a `file.gscbin` |`file.gsc` |
|
|`decomp` |decompile a `file.gscbin` |`file.gsc` |
|
||||||
|
|`parse` |parse a `file.gsc` |`file.gsc` |
|
||||||
|
|
||||||
## File Format
|
## File Format
|
||||||
If you need to extract scripts from fastfiles or game memory, use [Zonetool](https://github.com/ZoneTool/zonetool) or [Jekyll](https://github.com/EthanC/Jekyll).
|
If you need to extract scripts from fastfiles or game memory, use [Zonetool](https://github.com/ZoneTool/zonetool) or [Jekyll](https://github.com/EthanC/Jekyll).
|
||||||
|
@ -20,9 +20,10 @@
|
|||||||
%define parse.error detailed
|
%define parse.error detailed
|
||||||
%define parse.lac full
|
%define parse.lac full
|
||||||
%locations
|
%locations
|
||||||
%lex-param { xsk::gsc::lexer& lexer }
|
%lex-param { xsk::gsc::context const* ctx_ }
|
||||||
|
%lex-param { xsk::gsc::preprocessor& ppr }
|
||||||
%parse-param { xsk::gsc::context const* ctx_ }
|
%parse-param { xsk::gsc::context const* ctx_ }
|
||||||
%parse-param { xsk::gsc::lexer& lexer }
|
%parse-param { xsk::gsc::preprocessor& ppr }
|
||||||
%parse-param { xsk::gsc::program::ptr& ast }
|
%parse-param { xsk::gsc::program::ptr& ast }
|
||||||
%parse-param { std::uint32_t index }
|
%parse-param { std::uint32_t index }
|
||||||
|
|
||||||
@ -33,30 +34,23 @@
|
|||||||
#pragma warning(disable:4127)
|
#pragma warning(disable:4127)
|
||||||
#endif
|
#endif
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
namespace xsk::gsc { class lexer; }
|
namespace xsk::gsc { class preprocessor; }
|
||||||
}
|
}
|
||||||
|
|
||||||
%code top
|
%code top
|
||||||
{
|
{
|
||||||
#include "stdinc.hpp"
|
#include "stdinc.hpp"
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
#include "lexer.hpp"
|
#include "preprocessor.hpp"
|
||||||
using namespace xsk::gsc;
|
using namespace xsk::gsc;
|
||||||
namespace xsk::gsc
|
namespace xsk::gsc
|
||||||
{
|
{
|
||||||
auto GSClex(lexer& lexer) -> parser::symbol_type;
|
auto GSClex(context const* ctx_, preprocessor& ppr) -> parser::symbol_type;
|
||||||
auto parse_switch(stmt_switch& stm) -> void;
|
auto parse_switch(stmt_switch& stm) -> void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
%token SH_DEFINE "#define"
|
%token HASH "#"
|
||||||
%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 DEVBEGIN "/#"
|
||||||
%token DEVEND "#/"
|
%token DEVEND "#/"
|
||||||
%token INLINE "#inline"
|
%token INLINE "#inline"
|
||||||
@ -108,6 +102,7 @@ namespace xsk::gsc
|
|||||||
%token RBRACKET "]"
|
%token RBRACKET "]"
|
||||||
%token COMMA ","
|
%token COMMA ","
|
||||||
%token DOT "."
|
%token DOT "."
|
||||||
|
%token ELLIPSIS "..."
|
||||||
%token DOUBLECOLON "::"
|
%token DOUBLECOLON "::"
|
||||||
%token COLON ":"
|
%token COLON ":"
|
||||||
%token SEMICOLON ";"
|
%token SEMICOLON ";"
|
||||||
@ -289,7 +284,7 @@ program
|
|||||||
;
|
;
|
||||||
|
|
||||||
inline
|
inline
|
||||||
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
|
: INLINE expr_path SEMICOLON { ppr.push_header($2->value); }
|
||||||
;
|
;
|
||||||
|
|
||||||
include
|
include
|
||||||
@ -306,12 +301,12 @@ declaration
|
|||||||
|
|
||||||
decl_usingtree
|
decl_usingtree
|
||||||
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
|
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
|
||||||
{ lexer.ban_header(@$); $$ = make_decl_usingtree(@$, std::move($3)); }
|
{ ppr.ban_header(@$); $$ = make_decl_usingtree(@$, std::move($3)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
decl_function
|
decl_function
|
||||||
: expr_identifier LPAREN expr_parameters RPAREN stmt_comp
|
: expr_identifier LPAREN expr_parameters RPAREN stmt_comp
|
||||||
{ lexer.ban_header(@$); $$ = make_decl_function(@$, std::move($1), std::move($3), std::move($5)); }
|
{ ppr.ban_header(@$); $$ = make_decl_function(@$, std::move($1), std::move($3), std::move($5)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
stmt
|
stmt
|
||||||
@ -352,6 +347,10 @@ stmt_list
|
|||||||
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
|
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
|
||||||
| stmt
|
| stmt
|
||||||
{ $$ = make_stmt_list(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = make_stmt_list(@$); $$->list.push_back(std::move($1)); }
|
||||||
|
| stmt_list SEMICOLON
|
||||||
|
{ $$ = std::move($1); }
|
||||||
|
| SEMICOLON
|
||||||
|
{ $$ = make_stmt_list(@$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
stmt_or_dev_list
|
stmt_or_dev_list
|
||||||
@ -359,6 +358,10 @@ stmt_or_dev_list
|
|||||||
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
|
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
|
||||||
| stmt_or_dev
|
| stmt_or_dev
|
||||||
{ $$ = make_stmt_list(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = make_stmt_list(@$); $$->list.push_back(std::move($1)); }
|
||||||
|
| stmt_or_dev_list SEMICOLON
|
||||||
|
{ $$ = std::move($1); }
|
||||||
|
| SEMICOLON
|
||||||
|
{ $$ = make_stmt_list(@$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
stmt_dev
|
stmt_dev
|
||||||
@ -979,4 +982,207 @@ auto parse_switch(stmt_switch& stm) -> void
|
|||||||
stm.body->block = std::move(body);
|
stm.body->block = std::move(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern std::unordered_map<token::kind, parser::token::token_kind_type> const tok_to_parser;
|
||||||
|
extern std::unordered_map<std::string_view, parser::token::token_kind_type> const keyword_map;
|
||||||
|
|
||||||
|
auto map_token(context const* ctx_, token& tok) -> parser::symbol_type
|
||||||
|
{
|
||||||
|
if (tok.type == token::NAME)
|
||||||
|
{
|
||||||
|
tok.data = ctx_->make_token(tok.data);
|
||||||
|
|
||||||
|
auto const it = keyword_map.find(tok.data);
|
||||||
|
|
||||||
|
if (it != keyword_map.end())
|
||||||
|
{
|
||||||
|
if (it->second == parser::token::WAITFRAME)
|
||||||
|
{
|
||||||
|
if (ctx_->props() & props::waitframe)
|
||||||
|
return parser::symbol_type(it->second, tok.pos);
|
||||||
|
}
|
||||||
|
else if (it->second == parser::token::ISDEFINED || it->second == parser::token::ISTRUE)
|
||||||
|
{
|
||||||
|
if (ctx_->props() & props::boolfuncs)
|
||||||
|
{
|
||||||
|
parser::symbol_type(it->second, tok.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return parser::symbol_type(it->second, tok.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser::symbol_type(parser::token::IDENTIFIER, std::move(tok.data), tok.pos);
|
||||||
|
}
|
||||||
|
else if (tok.type == token::PATH ||tok.type == token::STRING ||tok.type == token::ISTRING || tok.type == token::INT ||tok.type == token::FLT)
|
||||||
|
{
|
||||||
|
auto it = tok_to_parser.find(tok.type);
|
||||||
|
|
||||||
|
if (it != tok_to_parser.end())
|
||||||
|
{
|
||||||
|
return parser::symbol_type(it->second, std::move(tok.data), tok.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto it = tok_to_parser.find(tok.type);
|
||||||
|
|
||||||
|
if (it != tok_to_parser.end())
|
||||||
|
{
|
||||||
|
return parser::symbol_type(it->second, tok.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error(fmt::format("unmapped token! {}", (u8)tok.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GSClex(context const* ctx_, preprocessor& ppr) -> parser::symbol_type
|
||||||
|
{
|
||||||
|
auto tok = ppr.process();
|
||||||
|
return map_token(ctx_, tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<token::kind, parser::token::token_kind_type> const tok_to_parser
|
||||||
|
{{
|
||||||
|
{ token::NAME, parser::token::IDENTIFIER },
|
||||||
|
{ token::PATH, parser::token::PATH },
|
||||||
|
{ token::STRING, parser::token::STRING },
|
||||||
|
{ token::ISTRING, parser::token::ISTRING },
|
||||||
|
{ token::INT, parser::token::INTEGER },
|
||||||
|
{ token::FLT, parser::token::FLOAT },
|
||||||
|
{ token::PLUS, parser::token::ADD },
|
||||||
|
{ token::MINUS, parser::token::SUB },
|
||||||
|
{ token::STAR, parser::token::MUL },
|
||||||
|
{ token::DIV, parser::token::DIV },
|
||||||
|
{ token::MOD, parser::token::MOD },
|
||||||
|
{ token::BITOR, parser::token::BITWISE_OR },
|
||||||
|
{ token::BITAND, parser::token::BITWISE_AND },
|
||||||
|
{ token::BITEXOR, parser::token::BITWISE_EXOR },
|
||||||
|
{ token::ASSIGN, parser::token::ASSIGN },
|
||||||
|
{ token::PLUSEQ, parser::token::ASSIGN_ADD },
|
||||||
|
{ token::MINUSEQ, parser::token::ASSIGN_SUB },
|
||||||
|
{ token::STAREQ, parser::token::ASSIGN_MUL },
|
||||||
|
{ token::DIVEQ, parser::token::ASSIGN_DIV },
|
||||||
|
{ token::MODEQ, parser::token::ASSIGN_MOD },
|
||||||
|
{ token::BITOREQ, parser::token::ASSIGN_BW_OR },
|
||||||
|
{ token::BITANDEQ, parser::token::ASSIGN_BW_AND },
|
||||||
|
{ token::BITEXOREQ, parser::token::ASSIGN_BW_EXOR },
|
||||||
|
{ token::SHLEQ, parser::token::ASSIGN_LSHIFT },
|
||||||
|
{ token::SHREQ, parser::token::ASSIGN_RSHIFT },
|
||||||
|
{ token::TILDE, parser::token::COMPLEMENT },
|
||||||
|
{ token::BANG, parser::token::NOT },
|
||||||
|
{ token::GT, parser::token::GREATER },
|
||||||
|
{ token::LT, parser::token::LESS },
|
||||||
|
{ token::GE, parser::token::GREATER_EQUAL },
|
||||||
|
{ token::LE, parser::token::LESS_EQUAL },
|
||||||
|
{ token::NE, parser::token::INEQUALITY },
|
||||||
|
{ token::EQ, parser::token::EQUALITY },
|
||||||
|
{ token::OR, parser::token::OR },
|
||||||
|
{ token::AND, parser::token::AND },
|
||||||
|
{ token::SHL, parser::token::LSHIFT },
|
||||||
|
{ token::SHR, parser::token::RSHIFT },
|
||||||
|
{ token::INC, parser::token::INCREMENT },
|
||||||
|
{ token::DEC, parser::token::DECREMENT },
|
||||||
|
{ token::QMARK, parser::token::QMARK },
|
||||||
|
{ token::DOT, parser::token::DOT },
|
||||||
|
{ token::ELLIPSIS, parser::token::ELLIPSIS },
|
||||||
|
{ token::COMMA, parser::token::COMMA },
|
||||||
|
{ token::COLON, parser::token::COLON },
|
||||||
|
{ token::SEMICOLON, parser::token::SEMICOLON },
|
||||||
|
{ token::DOUBLECOLON, parser::token::DOUBLECOLON },
|
||||||
|
{ token::LBRACKET, parser::token::LBRACKET },
|
||||||
|
{ token::RBRACKET, parser::token::RBRACKET },
|
||||||
|
{ token::LBRACE, parser::token::LBRACE },
|
||||||
|
{ token::RBRACE, parser::token::RBRACE },
|
||||||
|
{ token::LPAREN, parser::token::LPAREN },
|
||||||
|
{ token::RPAREN, parser::token::RPAREN },
|
||||||
|
{ token::DEVBEGIN, parser::token::DEVBEGIN },
|
||||||
|
{ token::DEVEND, parser::token::DEVEND },
|
||||||
|
{ token::INLINE, parser::token::INLINE },
|
||||||
|
{ token::INCLUDE, parser::token::INCLUDE },
|
||||||
|
{ token::USINGTREE, parser::token::USINGTREE },
|
||||||
|
{ token::ANIMTREE, parser::token::ANIMTREE },
|
||||||
|
{ token::ENDON, parser::token::ENDON },
|
||||||
|
{ token::NOTIFY, parser::token::NOTIFY },
|
||||||
|
{ token::WAIT, parser::token::WAIT },
|
||||||
|
{ token::WAITTILL, parser::token::WAITTILL },
|
||||||
|
{ token::WAITTILLMATCH, parser::token::WAITTILLMATCH },
|
||||||
|
{ token::WAITTILLFRAMEEND, parser::token::WAITTILLFRAMEEND },
|
||||||
|
{ token::WAITFRAME, parser::token::WAITFRAME },
|
||||||
|
{ token::IF, parser::token::IF },
|
||||||
|
{ token::ELSE, parser::token::ELSE },
|
||||||
|
{ token::DO, parser::token::DO },
|
||||||
|
{ token::WHILE, parser::token::WHILE },
|
||||||
|
{ token::FOR, parser::token::FOR },
|
||||||
|
{ token::FOREACH, parser::token::FOREACH },
|
||||||
|
{ token::IN, parser::token::IN },
|
||||||
|
{ token::SWITCH, parser::token::SWITCH },
|
||||||
|
{ token::CASE, parser::token::CASE },
|
||||||
|
{ token::DEFAULT, parser::token::DEFAULT },
|
||||||
|
{ token::BREAK, parser::token::BREAK },
|
||||||
|
{ token::CONTINUE, parser::token::CONTINUE },
|
||||||
|
{ token::RETURN, parser::token::RETURN },
|
||||||
|
{ token::BREAKPOINT, parser::token::BREAKPOINT },
|
||||||
|
{ token::PROFBEGIN, parser::token::PROFBEGIN },
|
||||||
|
{ token::PROFEND, parser::token::PROFEND },
|
||||||
|
{ token::THREAD, parser::token::THREAD },
|
||||||
|
{ token::CHILDTHREAD, parser::token::CHILDTHREAD },
|
||||||
|
{ token::THISTHREAD, parser::token::THISTHREAD },
|
||||||
|
{ token::CALL, parser::token::CALL },
|
||||||
|
{ token::TRUE, parser::token::TRUE },
|
||||||
|
{ token::FALSE, parser::token::FALSE },
|
||||||
|
{ token::UNDEFINED, parser::token::UNDEFINED },
|
||||||
|
{ token::SIZE, parser::token::SIZE },
|
||||||
|
{ token::GAME, parser::token::GAME },
|
||||||
|
{ token::SELF, parser::token::SELF },
|
||||||
|
{ token::ANIM, parser::token::ANIM },
|
||||||
|
{ token::LEVEL, parser::token::LEVEL },
|
||||||
|
{ token::ISDEFINED, parser::token::ISDEFINED },
|
||||||
|
{ token::ISTRUE, parser::token::ISTRUE },
|
||||||
|
{ token::EOS, parser::token::GSCEOF },
|
||||||
|
{ token::HASH, parser::token::HASH }
|
||||||
|
}};
|
||||||
|
|
||||||
|
std::unordered_map<std::string_view, parser::token::token_kind_type> const keyword_map
|
||||||
|
{{
|
||||||
|
{ "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 },
|
||||||
|
{ "isdefined", parser::token::ISDEFINED },
|
||||||
|
{ "istrue", parser::token::ISTRUE },
|
||||||
|
}};
|
||||||
|
|
||||||
} // namespace xsk::gsc
|
} // namespace xsk::gsc
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include "stdinc.hpp"
|
#include "stdinc.hpp"
|
||||||
#include "assembler.hpp"
|
#include "assembler.hpp"
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "utils/string.hpp"
|
|
||||||
|
|
||||||
namespace xsk::gsc
|
namespace xsk::gsc
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "stdinc.hpp"
|
#include "stdinc.hpp"
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "utils/string.hpp"
|
|
||||||
|
|
||||||
namespace xsk::gsc
|
namespace xsk::gsc
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ auto decompiler::decompile_function(function const& func) -> void
|
|||||||
decompile_instruction(*inst);
|
decompile_instruction(*inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack_.size())
|
if (!stack_.empty())
|
||||||
{
|
{
|
||||||
throw decomp_error("stack isn't empty at function end");
|
throw decomp_error("stack isn't empty at function end");
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ auto decompiler::decompile_function(function const& func) -> void
|
|||||||
decompile_statements(*func_->body->block);
|
decompile_statements(*func_->body->block);
|
||||||
process_function(*func_);
|
process_function(*func_);
|
||||||
|
|
||||||
program_->declarations.push_back(decl{ move(func_) });
|
program_->declarations.push_back(decl{ std::move(func_) });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto decompiler::decompile_instruction(instruction const& inst) -> void
|
auto decompiler::decompile_instruction(instruction const& inst) -> void
|
||||||
|
@ -11,195 +11,42 @@
|
|||||||
namespace xsk::gsc
|
namespace xsk::gsc
|
||||||
{
|
{
|
||||||
|
|
||||||
std::unordered_map<std::string_view, parser::token::token_kind_type> const keyword_map
|
lexer::lexer(context const* ctx, std::string const& name, char const* data, usize size) : ctx_{ ctx }, reader_{ data, size }, loc_{ &name }, buflen_{ 0 }, spacing_{ spacing::null }, indev_{ false }
|
||||||
{{
|
|
||||||
{ "#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 },
|
|
||||||
{ "isdefined", parser::token::ISDEFINED },
|
|
||||||
{ "istrue", parser::token::ISTRUE },
|
|
||||||
}};
|
|
||||||
|
|
||||||
auto GSClex(lexer& lexer) -> parser::symbol_type
|
|
||||||
{
|
|
||||||
return lexer.lex();
|
|
||||||
}
|
|
||||||
|
|
||||||
charbuf::charbuf() : length{ 0 }
|
|
||||||
{
|
|
||||||
data = static_cast<char*>(std::malloc(max_buf_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
charbuf::~charbuf()
|
|
||||||
{
|
|
||||||
if (data) std::free(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto charbuf::push(char c) -> bool
|
|
||||||
{
|
|
||||||
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 }
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
auto reader::init(char const* data, usize size) -> void
|
auto lexer::lex() -> token
|
||||||
{
|
{
|
||||||
if (data && size)
|
buflen_ = 0;
|
||||||
{
|
|
||||||
state = reader::ok;
|
|
||||||
buffer_pos = data;
|
|
||||||
bytes_remaining = static_cast<u32>(size);
|
|
||||||
last_byte = 0;
|
|
||||||
current_byte = *data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = reader::end;
|
|
||||||
buffer_pos = 0;
|
|
||||||
bytes_remaining = 0;
|
|
||||||
last_byte = 0;
|
|
||||||
current_byte = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto reader::advance() -> void
|
|
||||||
{
|
|
||||||
++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(context const* ctx, std::string const& name, char const* data, usize size)
|
|
||||||
: ctx_{ ctx }, loc_{ location{ &name } }, locs_{ std::stack<location>{} }, readers_{ std::stack<reader>{} }, header_top_{ 0 }, indev_{ false }, clean_{ true }
|
|
||||||
{
|
|
||||||
reader_.init(data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lexer::push_header(std::string const& file) -> void
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (header_top_++ >= 10)
|
|
||||||
throw comp_error(loc_, "maximum gsh depth exceeded '10'");
|
|
||||||
|
|
||||||
auto data = ctx_->header_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 (std::exception const& e)
|
|
||||||
{
|
|
||||||
throw error(fmt::format("parsing header file '{}': {}", file, e.what()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lexer::pop_header() -> void
|
|
||||||
{
|
|
||||||
header_top_--;
|
|
||||||
loc_ = locs_.top();
|
|
||||||
locs_.pop();
|
|
||||||
reader_ = readers_.top();
|
|
||||||
readers_.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lexer::ban_header(location const& loc) -> void
|
|
||||||
{
|
|
||||||
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)
|
while (true)
|
||||||
{
|
{
|
||||||
auto const& state = reader_.state;
|
|
||||||
auto& last = reader_.last_byte;
|
auto& last = reader_.last_byte;
|
||||||
auto& curr = reader_.current_byte;
|
auto& curr = reader_.curr_byte;
|
||||||
auto path = false;
|
auto path = false;
|
||||||
|
auto localize = false;
|
||||||
loc_.step();
|
loc_.step();
|
||||||
|
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
{
|
{
|
||||||
if (indev_)
|
if (indev_)
|
||||||
throw comp_error(loc_, "unmatched devblock start ('/#')");
|
throw comp_error(loc_, "unmatched devblock start ('/#')");
|
||||||
|
|
||||||
if (header_top_ > 0)
|
if (curr == 0 && last != '\n')
|
||||||
pop_header();
|
{
|
||||||
|
curr = -1;
|
||||||
|
return token{ token::NEWLINE, spacing_, loc_ };
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return parser::make_GSCEOF(loc_);
|
return token{ token::EOS, spacing_, loc_ };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clean_ && last != 0 && last != ' ' && last != '\t' && last != '\n')
|
if (last == 0 || last == '\n')
|
||||||
clean_ = false;
|
spacing_ = spacing::null;
|
||||||
|
else if (last == ' ' || last == '\t')
|
||||||
|
spacing_ = (spacing_ == spacing::null) ? spacing::empty : spacing::back;
|
||||||
|
else
|
||||||
|
spacing_ = spacing::none;
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
@ -213,18 +60,17 @@ auto lexer::lex() -> parser::symbol_type
|
|||||||
case '\n':
|
case '\n':
|
||||||
loc_.lines();
|
loc_.lines();
|
||||||
loc_.step();
|
loc_.step();
|
||||||
clean_ = true;
|
return token{ token::NEWLINE, spacing_, loc_ };
|
||||||
continue;
|
|
||||||
case '\\':
|
case '\\':
|
||||||
throw comp_error(loc_, "invalid token ('\\')");
|
throw comp_error(loc_, "invalid token ('\\')");
|
||||||
case '/':
|
case '/':
|
||||||
if (curr != '=' && curr != '#' && curr != '@' && curr != '*' && curr != '/')
|
if (curr != '=' && curr != '#' && curr != '@' && curr != '*' && curr != '/')
|
||||||
return parser::make_DIV(loc_);
|
return token{ token::DIV, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (last == '=')
|
if (last == '=')
|
||||||
return parser::make_ASSIGN_DIV(loc_);
|
return token{ token::DIVEQ, spacing_, loc_ };
|
||||||
|
|
||||||
if (last == '#')
|
if (last == '#')
|
||||||
{
|
{
|
||||||
@ -234,13 +80,13 @@ auto lexer::lex() -> parser::symbol_type
|
|||||||
if (ctx_->build() == build::dev)
|
if (ctx_->build() == build::dev)
|
||||||
{
|
{
|
||||||
indev_ = true;
|
indev_ = true;
|
||||||
return parser::make_DEVBEGIN(loc_);
|
return token{ token::DEVBEGIN, spacing_, loc_ };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
throw comp_error(loc_, "unmatched devblock start ('/#')");
|
throw comp_error(loc_, "unmatched devblock start ('/#')");
|
||||||
|
|
||||||
if (curr == '\n')
|
if (curr == '\n')
|
||||||
@ -262,7 +108,7 @@ auto lexer::lex() -> parser::symbol_type
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
throw comp_error(loc_, "unmatched script doc comment start ('/@')");
|
throw comp_error(loc_, "unmatched script doc comment start ('/@')");
|
||||||
|
|
||||||
if (curr == '\n')
|
if (curr == '\n')
|
||||||
@ -283,7 +129,7 @@ auto lexer::lex() -> parser::symbol_type
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
throw comp_error(loc_, "unmatched multiline comment start ('/*')");
|
throw comp_error(loc_, "unmatched multiline comment start ('/*')");
|
||||||
|
|
||||||
if (curr == '\n')
|
if (curr == '\n')
|
||||||
@ -304,7 +150,7 @@ auto lexer::lex() -> parser::symbol_type
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (curr == '\n')
|
if (curr == '\n')
|
||||||
@ -322,164 +168,148 @@ auto lexer::lex() -> parser::symbol_type
|
|||||||
|
|
||||||
advance();
|
advance();
|
||||||
indev_ = false;
|
indev_ = false;
|
||||||
return parser::make_DEVEND(loc_);
|
return token{ token::DEVEND, spacing_, loc_ };
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_.push(last);
|
return token{ token::SHARP, spacing_, loc_ };
|
||||||
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 '*':
|
case '*':
|
||||||
if (curr != '=' && curr != '/')
|
if (curr != '=' && curr != '/')
|
||||||
return parser::make_MUL(loc_);
|
return token{ token::STAR, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (last == '=')
|
if (last == '=')
|
||||||
return parser::make_ASSIGN_MUL(loc_);
|
return token{ token::STAREQ, spacing_, loc_ };
|
||||||
|
|
||||||
throw comp_error(loc_, "unmatched multiline comment end ('*/')");
|
throw comp_error(loc_, "unmatched multiline comment end ('*/')");
|
||||||
case '"':
|
case '"':
|
||||||
state_ = state::string;
|
|
||||||
goto lex_string;
|
goto lex_string;
|
||||||
case '.':
|
case '.':
|
||||||
if (curr < '0' || curr > '9')
|
if (curr < '0' || curr > '9')
|
||||||
return parser::make_DOT(loc_);
|
return token{ token::DOT, spacing_, loc_ };
|
||||||
goto lex_number;
|
goto lex_number;
|
||||||
case '(':
|
case '(':
|
||||||
return parser::make_LPAREN(loc_);
|
return token{ token::LPAREN, spacing_, loc_ };
|
||||||
case ')':
|
case ')':
|
||||||
return parser::make_RPAREN(loc_);
|
return token{ token::RPAREN, spacing_, loc_ };
|
||||||
case '{':
|
case '{':
|
||||||
return parser::make_LBRACE(loc_);
|
return token{ token::LBRACE, spacing_, loc_ };
|
||||||
case '}':
|
case '}':
|
||||||
return parser::make_RBRACE(loc_);
|
return token{ token::RBRACE, spacing_, loc_ };
|
||||||
case '[':
|
case '[':
|
||||||
return parser::make_LBRACKET(loc_);
|
return token{ token::LBRACKET, spacing_, loc_ };
|
||||||
case ']':
|
case ']':
|
||||||
return parser::make_RBRACKET(loc_);
|
return token{ token::RBRACKET, spacing_, loc_ };
|
||||||
case ',':
|
case ',':
|
||||||
return parser::make_COMMA(loc_);
|
return token{ token::COMMA, spacing_, loc_ };
|
||||||
case ';':
|
case ';':
|
||||||
return parser::make_SEMICOLON(loc_);
|
return token{ token::SEMICOLON, spacing_, loc_ };
|
||||||
case ':':
|
case ':':
|
||||||
if (curr != ':')
|
if (curr != ':')
|
||||||
return parser::make_COLON(loc_);
|
return token{ token::COLON, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
return parser::make_DOUBLECOLON(loc_);
|
return token{ token::DOUBLECOLON, spacing_, loc_ };
|
||||||
case '?':
|
case '?':
|
||||||
return parser::make_QMARK(loc_);
|
return token{ token::QMARK, spacing_, loc_ };
|
||||||
case '=':
|
case '=':
|
||||||
if (curr != '=')
|
if (curr != '=')
|
||||||
return parser::make_ASSIGN(loc_);
|
return token{ token::ASSIGN, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
return parser::make_EQUALITY(loc_);
|
return token{ token::EQ, spacing_, loc_ };
|
||||||
case '+':
|
case '+':
|
||||||
if (curr != '+' && curr != '=')
|
if (curr != '+' && curr != '=')
|
||||||
return parser::make_ADD(loc_);
|
return token{ token::PLUS, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (last == '+')
|
if (last == '+')
|
||||||
return parser::make_INCREMENT(loc_);
|
return token{ token::INC, spacing_, loc_ };
|
||||||
|
|
||||||
return parser::make_ASSIGN_ADD(loc_);
|
return token{ token::PLUSEQ, spacing_, loc_ };
|
||||||
case '-':
|
case '-':
|
||||||
if (curr != '-' && curr != '=')
|
if (curr != '-' && curr != '=')
|
||||||
return parser::make_SUB(loc_);
|
return token{ token::MINUS, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (last == '-')
|
if (last == '-')
|
||||||
return parser::make_DECREMENT(loc_);
|
return token{ token::DEC, spacing_, loc_ };
|
||||||
|
|
||||||
return parser::make_ASSIGN_SUB(loc_);
|
return token{ token::MINUSEQ, spacing_, loc_ };
|
||||||
case '%':
|
case '%':
|
||||||
if (curr != '=')
|
if (curr != '=')
|
||||||
return parser::make_MOD(loc_);
|
return token{ token::MOD, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
return parser::make_ASSIGN_MOD(loc_);
|
return token{ token::MODEQ, spacing_, loc_ };
|
||||||
case '|':
|
case '|':
|
||||||
if (curr != '|' && curr != '=')
|
if (curr != '|' && curr != '=')
|
||||||
return parser::make_BITWISE_OR(loc_);
|
return token{ token::BITOR, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (last == '|')
|
if (last == '|')
|
||||||
return parser::make_OR(loc_);
|
return token{ token::OR, spacing_, loc_ };
|
||||||
|
|
||||||
return parser::make_ASSIGN_BW_OR(loc_);
|
return token{ token::BITOREQ, spacing_, loc_ };
|
||||||
case '&':
|
case '&':
|
||||||
if (curr != '&' && curr != '=' && curr != '"')
|
if (curr != '&' && curr != '=' && curr != '"')
|
||||||
return parser::make_BITWISE_AND(loc_);
|
return token{ token::BITAND, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (last == '&')
|
if (last == '&')
|
||||||
return parser::make_AND(loc_);
|
return token{ token::AND, spacing_, loc_ };
|
||||||
|
|
||||||
if (last == '=')
|
if (last == '=')
|
||||||
return parser::make_ASSIGN_BW_AND(loc_);
|
return token{ token::BITANDEQ, spacing_, loc_ };
|
||||||
|
|
||||||
state_ = state::localize;
|
localize = true;
|
||||||
goto lex_string;
|
goto lex_string;
|
||||||
case '^':
|
case '^':
|
||||||
if (curr != '=')
|
if (curr != '=')
|
||||||
return parser::make_BITWISE_EXOR(loc_);
|
return token{ token::BITEXOR, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
return parser::make_ASSIGN_BW_EXOR(loc_);
|
return token{ token::BITEXOREQ, spacing_, loc_ };
|
||||||
case '!':
|
case '!':
|
||||||
if (curr != '=')
|
if (curr != '=')
|
||||||
return parser::make_NOT(loc_);
|
return token{ token::BANG, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
return parser::make_INEQUALITY(loc_);
|
return token{ token::NE, spacing_, loc_ };
|
||||||
case '~':
|
case '~':
|
||||||
return parser::make_COMPLEMENT(loc_);
|
return token{ token::TILDE, spacing_, loc_ };
|
||||||
case '<':
|
case '<':
|
||||||
if (curr != '<' && curr != '=')
|
if (curr != '<' && curr != '=')
|
||||||
return parser::make_LESS(loc_);
|
return token{ token::LT, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
if (last == '=')
|
if (last == '=')
|
||||||
return parser::make_LESS_EQUAL(loc_);
|
return token{ token::LE, spacing_, loc_ };
|
||||||
|
|
||||||
if (curr != '=')
|
if (curr != '=')
|
||||||
return parser::make_LSHIFT(loc_);
|
return token{ token::SHL, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
return parser::make_ASSIGN_LSHIFT(loc_);
|
return token{ token::SHLEQ, spacing_, loc_ };
|
||||||
case '>':
|
case '>':
|
||||||
if (curr != '>' && curr != '=')
|
if (curr != '>' && curr != '=')
|
||||||
return parser::make_GREATER(loc_);
|
return token{ token::GT, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (last == '=')
|
if (last == '=')
|
||||||
return parser::make_GREATER_EQUAL(loc_);
|
return token{ token::GE, spacing_, loc_ };
|
||||||
|
|
||||||
if (curr != '=')
|
if (curr != '=')
|
||||||
return parser::make_RSHIFT(loc_);
|
return token{ token::SHR, spacing_, loc_ };
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
return parser::make_ASSIGN_RSHIFT(loc_);
|
return token{ token::SHREQ, spacing_, loc_ };
|
||||||
default:
|
default:
|
||||||
if (last >= '0' && last <= '9')
|
if (last >= '0' && last <= '9')
|
||||||
goto lex_number;
|
goto lex_number;
|
||||||
@ -492,7 +322,7 @@ auto lexer::lex() -> parser::symbol_type
|
|||||||
lex_string:
|
lex_string:
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
throw comp_error(loc_, "unmatched string start ('\"')");
|
throw comp_error(loc_, "unmatched string start ('\"')");
|
||||||
|
|
||||||
if (curr == '"')
|
if (curr == '"')
|
||||||
@ -508,7 +338,7 @@ lex_string:
|
|||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
throw comp_error(loc_, "invalid token ('\')");
|
throw comp_error(loc_, "invalid token ('\')");
|
||||||
|
|
||||||
char c = curr;
|
char c = curr;
|
||||||
@ -522,26 +352,25 @@ lex_string:
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buffer_.push(c))
|
push(c);
|
||||||
throw comp_error(loc_, "max string size exceeded");
|
|
||||||
}
|
}
|
||||||
else if (!buffer_.push(curr))
|
else
|
||||||
throw comp_error(loc_, "max string size exceeded");
|
push(curr);
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state_ == state::localize)
|
if (localize)
|
||||||
return parser::make_ISTRING(std::string{ buffer_.data, buffer_.length }, loc_);
|
return token{ token::ISTRING, spacing_, loc_, std::string{ &buffer_[0], buflen_ } };
|
||||||
|
|
||||||
return parser::make_STRING(std::string{ buffer_.data, buffer_.length }, loc_);
|
return token{ token::STRING, spacing_, loc_, std::string{ &buffer_[0], buflen_ } };
|
||||||
|
|
||||||
lex_name:
|
lex_name:
|
||||||
buffer_.push(last);
|
push(last);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!(curr == '\\' || curr == '_' || (curr > 64 && curr < 91) || (curr > 96 && curr < 123) || (curr > 47 && curr < 58)))
|
if (!(curr == '\\' || curr == '_' || (curr > 64 && curr < 91) || (curr > 96 && curr < 123) || (curr > 47 && curr < 58)))
|
||||||
@ -553,95 +382,35 @@ lex_name:
|
|||||||
throw comp_error(loc_, "invalid path '\\\\'");
|
throw comp_error(loc_, "invalid path '\\\\'");
|
||||||
|
|
||||||
path = true;
|
path = true;
|
||||||
if (!buffer_.push('/'))
|
push('/');
|
||||||
throw comp_error(loc_, "max string size exceeded");
|
|
||||||
}
|
}
|
||||||
else if (!buffer_.push(curr))
|
else
|
||||||
throw comp_error(loc_, "max string size exceeded");
|
push(curr);
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state_ == state::preprocessor)
|
|
||||||
{
|
|
||||||
auto token = parser::token::GSCUNDEF;
|
|
||||||
|
|
||||||
if (buffer_.length < 16)
|
|
||||||
{
|
|
||||||
auto const 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_.data[0] != '_')
|
|
||||||
{
|
|
||||||
for (auto i = 0u; i < buffer_.length; i++)
|
|
||||||
{
|
|
||||||
auto c = buffer_.data[i];
|
|
||||||
|
|
||||||
if (c > 64 && c < 91)
|
|
||||||
buffer_.data[i] = c + 32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_.length < 17)
|
|
||||||
{
|
|
||||||
auto const itr = keyword_map.find(std::string_view(buffer_.data, buffer_.length));
|
|
||||||
|
|
||||||
if (itr != keyword_map.end())
|
|
||||||
{
|
|
||||||
if (itr->second == parser::token::WAITFRAME)
|
|
||||||
{
|
|
||||||
if (ctx_->props() & props::waitframe)
|
|
||||||
return parser::symbol_type(itr->second, loc_);
|
|
||||||
}
|
|
||||||
else if (itr->second == parser::token::ISDEFINED || itr->second == parser::token::ISTRUE)
|
|
||||||
{
|
|
||||||
if (ctx_->props() & props::boolfuncs)
|
|
||||||
return parser::symbol_type(itr->second, loc_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return parser::symbol_type(itr->second, loc_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path)
|
if (path)
|
||||||
{
|
{
|
||||||
if (buffer_.data[buffer_.length - 1] == '/')
|
if (buffer_[buflen_ - 1] == '/')
|
||||||
throw comp_error(loc_, "invalid path end '\\'");
|
throw comp_error(loc_, "invalid path end '\\'");
|
||||||
|
|
||||||
return parser::make_PATH(ctx_->make_token(std::string_view(buffer_.data, buffer_.length)), loc_);
|
return token{ token::PATH, spacing_, loc_, ctx_->make_token(std::string_view{ &buffer_[0], buflen_ }) };
|
||||||
}
|
}
|
||||||
|
|
||||||
return parser::make_IDENTIFIER(ctx_->make_token(std::string_view(buffer_.data, buffer_.length)), loc_);
|
return token{ token::NAME, spacing_, loc_, std::string{ &buffer_[0], buflen_ } };
|
||||||
}
|
|
||||||
|
|
||||||
lex_number:
|
lex_number:
|
||||||
if (last == '.' || last != '0' || (last == '0' && (curr != 'o' && curr != 'b' && curr != 'x')))
|
if (last == '.' || last != '0' || (last == '0' && (curr != 'o' && curr != 'b' && curr != 'x')))
|
||||||
{
|
{
|
||||||
buffer_.push(last);
|
push(last);
|
||||||
|
|
||||||
auto dot = last == '.' ? 1 : 0;
|
auto dot = last == '.' ? 1 : 0;
|
||||||
auto flt = 0;
|
auto flt = 0;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (curr == '\'' && (last == '\'' || last == 'f' || last == '.'))
|
if (curr == '\'' && (last == '\'' || last == 'f' || last == '.'))
|
||||||
@ -663,22 +432,20 @@ lex_number:
|
|||||||
else if (!(curr > 47 && curr < 58))
|
else if (!(curr > 47 && curr < 58))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!buffer_.push(curr))
|
push(curr);
|
||||||
throw comp_error(loc_, "number literal size exceeded");
|
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last == '\'')
|
if (last == '\'')
|
||||||
throw comp_error(loc_, "invalid number literal");
|
throw comp_error(loc_, "invalid number literal");
|
||||||
|
|
||||||
if (dot > 1 || flt > 1 || (flt && buffer_.data[buffer_.length - 1] != 'f'))
|
if (dot > 1 || flt > 1 || (flt && buffer_[buflen_ - 1] != 'f'))
|
||||||
throw comp_error(loc_, "invalid number literal");
|
throw comp_error(loc_, "invalid number literal");
|
||||||
|
|
||||||
if (dot || flt)
|
if (dot || flt)
|
||||||
return parser::make_FLOAT(std::string{ buffer_.data, buffer_.length }, loc_);
|
return token{ token::FLT, spacing_, loc_, std::string{ &buffer_[0], buflen_ } };
|
||||||
|
|
||||||
return parser::make_INTEGER(std::string{ buffer_.data, buffer_.length }, loc_);
|
return token{ token::INT, spacing_, loc_, std::string{ &buffer_[0], buflen_ } };
|
||||||
}
|
}
|
||||||
else if (curr == 'o')
|
else if (curr == 'o')
|
||||||
{
|
{
|
||||||
@ -686,7 +453,7 @@ lex_number:
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((curr == '\'' && (last == '\'' || last == 'o')) || (curr == 'o' && last == '\''))
|
if ((curr == '\'' && (last == '\'' || last == 'o')) || (curr == 'o' && last == '\''))
|
||||||
@ -701,26 +468,26 @@ lex_number:
|
|||||||
if (!(curr > 47 && curr < 56))
|
if (!(curr > 47 && curr < 56))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!buffer_.push(curr))
|
push(curr);
|
||||||
throw error("gsc lexer: out of memory");
|
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last == '\'' || buffer_.length <= 0)
|
if (last == '\'' || buflen_ <= 0)
|
||||||
throw comp_error(loc_, "invalid octal literal");
|
throw comp_error(loc_, "invalid octal literal");
|
||||||
|
|
||||||
return parser::make_INTEGER(utils::string::oct_to_dec(buffer_.data), loc_);
|
push('\0');
|
||||||
|
|
||||||
|
return token{ token::INT, spacing_, loc_, utils::string::oct_to_dec(&buffer_[0]) };
|
||||||
}
|
}
|
||||||
else if (curr == 'b')
|
else if (curr == 'b')
|
||||||
{
|
{
|
||||||
buffer_.push(last);
|
push(last);
|
||||||
buffer_.push(curr);
|
push(curr);
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((curr == '\'' && (last == '\'' || last == 'b')) || (curr == 'b' && last == '\''))
|
if ((curr == '\'' && (last == '\'' || last == 'b')) || (curr == 'b' && last == '\''))
|
||||||
@ -735,26 +502,26 @@ lex_number:
|
|||||||
if (curr != '0' && curr != '1')
|
if (curr != '0' && curr != '1')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!buffer_.push(curr))
|
push(curr);
|
||||||
throw comp_error(loc_, "number literal size exceeded");
|
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last == '\'' || buffer_.length < 3)
|
if (last == '\'' || buflen_ < 3)
|
||||||
throw comp_error(loc_, "invalid binary literal");
|
throw comp_error(loc_, "invalid binary literal");
|
||||||
|
|
||||||
return parser::make_INTEGER(utils::string::bin_to_dec(buffer_.data), loc_);
|
push('\0');
|
||||||
|
|
||||||
|
return token{ token::INT, spacing_, loc_, utils::string::bin_to_dec(&buffer_[0]) };
|
||||||
}
|
}
|
||||||
else if (curr == 'x')
|
else if (curr == 'x')
|
||||||
{
|
{
|
||||||
buffer_.push(last);
|
push(last);
|
||||||
buffer_.push(curr);
|
push(curr);
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state == reader::end)
|
if (reader_.ended())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((curr == '\'' && (last == '\'' || last == 'x')) || (curr == 'x' && last == '\''))
|
if ((curr == '\'' && (last == '\'' || last == 'x')) || (curr == 'x' && last == '\''))
|
||||||
@ -769,36 +536,44 @@ lex_number:
|
|||||||
if (!((curr > 47 && curr < 58) || (curr > 64 && curr < 71) || (curr > 96 && curr < 103)))
|
if (!((curr > 47 && curr < 58) || (curr > 64 && curr < 71) || (curr > 96 && curr < 103)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!buffer_.push(curr))
|
push(curr);
|
||||||
throw error("gsc lexer: out of memory");
|
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last == '\'' || buffer_.length < 3)
|
if (last == '\'' || buflen_ < 3)
|
||||||
throw comp_error(loc_, "invalid hexadecimal literal");
|
throw comp_error(loc_, "invalid hexadecimal literal");
|
||||||
|
|
||||||
return parser::make_INTEGER(utils::string::hex_to_dec(buffer_.data), loc_);
|
push('\0');
|
||||||
|
|
||||||
|
return token{ token::INT, spacing_, loc_, utils::string::hex_to_dec(&buffer_[0]) };
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error("UNEXPECTED LEXER INTERNAL ERROR");
|
throw error("UNEXPECTED LEXER INTERNAL ERROR");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto lexer::push(char c) -> void
|
||||||
|
{
|
||||||
|
if (buflen_ >= 0x1000)
|
||||||
|
throw error("lexer: max literal size exceeded");
|
||||||
|
|
||||||
|
buffer_[buflen_++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
auto lexer::advance() -> void
|
auto lexer::advance() -> void
|
||||||
{
|
{
|
||||||
reader_.advance();
|
reader_.advance();
|
||||||
loc_.end.column++;
|
loc_.end.column++;
|
||||||
|
|
||||||
if (reader_.current_byte == '\\') [[unlikely]]
|
if (reader_.curr_byte == '\\') [[unlikely]]
|
||||||
preprocessor_wrap();
|
linewrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lexer::preprocessor_wrap() -> void
|
auto lexer::linewrap() -> void
|
||||||
{
|
{
|
||||||
while (reader_.current_byte == '\\')
|
while (reader_.curr_byte == '\\')
|
||||||
{
|
{
|
||||||
if (reader_.bytes_remaining == 1)
|
if (reader_.available == 1)
|
||||||
throw comp_error(loc_, "invalid token ('\\')");
|
throw comp_error(loc_, "invalid token ('\\')");
|
||||||
|
|
||||||
if (reader_.buffer_pos[1] != '\r' && reader_.buffer_pos[1] != '\n')
|
if (reader_.buffer_pos[1] != '\r' && reader_.buffer_pos[1] != '\n')
|
||||||
@ -806,71 +581,27 @@ auto lexer::preprocessor_wrap() -> void
|
|||||||
|
|
||||||
if (reader_.buffer_pos[1] == '\r')
|
if (reader_.buffer_pos[1] == '\r')
|
||||||
{
|
{
|
||||||
if (reader_.bytes_remaining <= 3 || reader_.buffer_pos[2] != '\n')
|
if (reader_.available <= 3 || reader_.buffer_pos[2] != '\n')
|
||||||
throw comp_error(loc_, "invalid token ('\\')");
|
throw comp_error(loc_, "invalid token ('\\')");
|
||||||
|
|
||||||
reader_.buffer_pos += 3;
|
reader_.buffer_pos += 3;
|
||||||
reader_.bytes_remaining -= 3;
|
reader_.available -= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((reader_.buffer_pos[1] == '\n'))
|
if ((reader_.buffer_pos[1] == '\n'))
|
||||||
{
|
{
|
||||||
if (reader_.bytes_remaining == 2)
|
if (reader_.available == 2)
|
||||||
throw comp_error(loc_, "invalid token ('\\')");
|
throw comp_error(loc_, "invalid token ('\\')");
|
||||||
|
|
||||||
reader_.buffer_pos += 2;
|
reader_.buffer_pos += 2;
|
||||||
reader_.bytes_remaining -= 2;
|
reader_.available -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader_.bytes_remaining == 0)
|
reader_.curr_byte = reader_.available ? *reader_.buffer_pos : 0;
|
||||||
{
|
|
||||||
reader_.state = reader::end;
|
|
||||||
reader_.current_byte = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reader_.current_byte = *reader_.buffer_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
loc_.lines();
|
loc_.lines();
|
||||||
loc_.step();
|
loc_.step();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lexer::preprocessor_run(parser::token::token_kind_type token) -> void
|
|
||||||
{
|
|
||||||
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
|
} // namespace xsk::gsc
|
||||||
|
@ -6,76 +6,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "misc/types.hpp"
|
#include "misc/types.hpp"
|
||||||
#include "parser.hpp"
|
|
||||||
|
|
||||||
namespace xsk::gsc
|
namespace xsk::gsc
|
||||||
{
|
{
|
||||||
|
|
||||||
constexpr usize max_buf_size = 0x2000;
|
|
||||||
|
|
||||||
struct charbuf
|
|
||||||
{
|
|
||||||
char* data;
|
|
||||||
usize length;
|
|
||||||
|
|
||||||
charbuf();
|
|
||||||
~charbuf();
|
|
||||||
auto push(char c) -> bool;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct reader
|
|
||||||
{
|
|
||||||
enum state_type : u8 { end, ok };
|
|
||||||
|
|
||||||
char const* buffer_pos;
|
|
||||||
u32 bytes_remaining;
|
|
||||||
char last_byte;
|
|
||||||
char current_byte;
|
|
||||||
state_type state;
|
|
||||||
|
|
||||||
reader();
|
|
||||||
|
|
||||||
reader(reader const& obj)
|
|
||||||
{
|
|
||||||
std::memcpy(this, &obj, sizeof(reader));
|
|
||||||
}
|
|
||||||
|
|
||||||
reader& operator=(reader const& obj)
|
|
||||||
{
|
|
||||||
std::memcpy(this, &obj, sizeof(reader));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto init(char const* data, usize size) -> void;
|
|
||||||
auto advance() -> void;
|
|
||||||
};
|
|
||||||
|
|
||||||
class lexer
|
class lexer
|
||||||
{
|
{
|
||||||
enum class state : u8 { start, string, localize, preprocessor };
|
|
||||||
|
|
||||||
context const* ctx_;
|
context const* ctx_;
|
||||||
reader reader_;
|
lookahead reader_;
|
||||||
charbuf buffer_;
|
|
||||||
location loc_;
|
location loc_;
|
||||||
std::stack<location> locs_;
|
usize buflen_;
|
||||||
std::stack<reader> readers_;
|
spacing spacing_;
|
||||||
u32 header_top_;
|
|
||||||
state state_;
|
|
||||||
bool indev_;
|
bool indev_;
|
||||||
bool clean_;
|
std::array<char, 0x1000> buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
lexer(context const* ctx, std::string const& name, char const* data, usize size);
|
lexer(context const* ctx, std::string const& name, char const* data, usize size);
|
||||||
auto lex() -> parser::symbol_type;
|
auto lex() -> token;
|
||||||
auto push_header(std::string const& file) -> void;
|
|
||||||
auto pop_header() -> void;
|
|
||||||
auto ban_header(location const& loc) -> void;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
auto push(char c) -> void;
|
||||||
auto advance() -> void;
|
auto advance() -> void;
|
||||||
auto preprocessor_wrap() -> void;
|
auto linewrap() -> void;
|
||||||
auto preprocessor_run(parser::token::token_kind_type token) -> void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xsk::gsc
|
} // namespace xsk::gsc
|
||||||
|
20
src/gsc/misc/define.hpp
Normal file
20
src/gsc/misc/define.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2023 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
|
||||||
|
{
|
||||||
|
|
||||||
|
struct define
|
||||||
|
{
|
||||||
|
enum kind { PLAIN, BUILTIN, OBJECT, FUNCTION };
|
||||||
|
|
||||||
|
kind type;
|
||||||
|
std::vector<token> args;
|
||||||
|
std::vector<token> exp;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
19
src/gsc/misc/directive.hpp
Normal file
19
src/gsc/misc/directive.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2023 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
|
||||||
|
{
|
||||||
|
|
||||||
|
struct directive
|
||||||
|
{
|
||||||
|
enum kind : u8 { IF, IFDEF, IFNDEF, ELIF, ELIFDEF, ELIFNDEF, ELSE, ENDIF, DEFINE, UNDEF, PRAGMA, WARNING, ERROR, LINE, INCLUDE, INLINE, INSERT, USINGTREE };
|
||||||
|
|
||||||
|
kind type;
|
||||||
|
bool skip;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
@ -22,6 +22,10 @@ disasm_error::disasm_error(std::string const& what) : std::runtime_error(fmt::fo
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ppr_error::ppr_error(location const& loc, std::string const& what) : std::runtime_error(fmt::format("[ERROR]:preprocessor:{}: {}", loc.print(), what))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
comp_error::comp_error(location const& loc, std::string const& what) : std::runtime_error(fmt::format("[ERROR]:compiler:{}: {}", loc.print(), what))
|
comp_error::comp_error(location const& loc, std::string const& what) : std::runtime_error(fmt::format("[ERROR]:compiler:{}: {}", loc.print(), what))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,12 @@ public:
|
|||||||
disasm_error(std::string const& what);
|
disasm_error(std::string const& what);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ppr_error : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ppr_error(location const& loc, std::string const& what);
|
||||||
|
};
|
||||||
|
|
||||||
class comp_error : public std::runtime_error
|
class comp_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
40
src/gsc/misc/lookahead.cpp
Normal file
40
src/gsc/misc/lookahead.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2023 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 "stdinc.hpp"
|
||||||
|
#include "lookahead.hpp"
|
||||||
|
|
||||||
|
namespace xsk::gsc
|
||||||
|
{
|
||||||
|
|
||||||
|
lookahead::lookahead(char const* data, usize size) : buffer_pos{ 0 }, available{ 0 }, last_byte{ 0 }, curr_byte{ 0 }
|
||||||
|
{
|
||||||
|
if (data && size)
|
||||||
|
{
|
||||||
|
buffer_pos = data;
|
||||||
|
available = size;
|
||||||
|
last_byte = 0;
|
||||||
|
curr_byte = *data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lookahead::advance() -> void
|
||||||
|
{
|
||||||
|
++buffer_pos;
|
||||||
|
|
||||||
|
if (available-- == 1)
|
||||||
|
{
|
||||||
|
available = 0;
|
||||||
|
last_byte = curr_byte;
|
||||||
|
curr_byte = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_byte = curr_byte;
|
||||||
|
curr_byte = *buffer_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
23
src/gsc/misc/lookahead.hpp
Normal file
23
src/gsc/misc/lookahead.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2023 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
|
||||||
|
{
|
||||||
|
|
||||||
|
struct lookahead
|
||||||
|
{
|
||||||
|
char const* buffer_pos;
|
||||||
|
usize available;
|
||||||
|
char last_byte;
|
||||||
|
char curr_byte;
|
||||||
|
|
||||||
|
lookahead(char const* data, usize size);
|
||||||
|
auto advance() -> void;
|
||||||
|
auto ended() { return available == 0; };
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
19
src/gsc/misc/space.hpp
Normal file
19
src/gsc/misc/space.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2023 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
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class spacing : u8
|
||||||
|
{
|
||||||
|
none = 0, // no space between tokens
|
||||||
|
null = 1, // token just after new line
|
||||||
|
back = 2, // token after space
|
||||||
|
empty = 4, // token after new line + space
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
14
src/gsc/misc/token.cpp
Normal file
14
src/gsc/misc/token.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2023 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 "stdinc.hpp"
|
||||||
|
#include "location.hpp"
|
||||||
|
#include "space.hpp"
|
||||||
|
#include "token.hpp"
|
||||||
|
|
||||||
|
namespace xsk::gsc
|
||||||
|
{
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
40
src/gsc/misc/token.hpp
Normal file
40
src/gsc/misc/token.hpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2023 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
|
||||||
|
{
|
||||||
|
|
||||||
|
struct token
|
||||||
|
{
|
||||||
|
enum kind : u8
|
||||||
|
{
|
||||||
|
PLUS, MINUS, STAR, DIV, MOD, BITOR, BITAND, BITEXOR, SHL, SHR,
|
||||||
|
ASSIGN, PLUSEQ, MINUSEQ, STAREQ, DIVEQ, MODEQ, BITOREQ, BITANDEQ, BITEXOREQ, SHLEQ, SHREQ,
|
||||||
|
INC, DEC, GT, LT, GE, LE, NE, EQ, OR, AND, TILDE, BANG, QMARK, COLON, SHARP, COMMA,
|
||||||
|
DOT, ELLIPSIS, SEMICOLON, DOUBLECOLON, LBRACKET, RBRACKET, LBRACE, RBRACE, LPAREN, RPAREN,
|
||||||
|
|
||||||
|
NAME, PATH, STRING, ISTRING, INT, FLT,
|
||||||
|
|
||||||
|
DEVBEGIN, DEVEND, INLINE, INCLUDE, USINGTREE, ANIMTREE, ENDON, NOTIFY, WAIT,
|
||||||
|
WAITTILL, WAITTILLMATCH, WAITTILLFRAMEEND, WAITFRAME, IF, ELSE, DO, WHILE,
|
||||||
|
FOR, FOREACH, IN, SWITCH, CASE, DEFAULT, BREAK, CONTINUE, RETURN, BREAKPOINT,
|
||||||
|
PROFBEGIN, PROFEND, THREAD, CHILDTHREAD, THISTHREAD, CALL, TRUE, FALSE, UNDEFINED,
|
||||||
|
SIZE, GAME, SELF, ANIM, LEVEL, ISDEFINED, ISTRUE,
|
||||||
|
|
||||||
|
HASH, NEWLINE, EOS, DEFINED, MACROBEGIN, MACROEND,
|
||||||
|
};
|
||||||
|
|
||||||
|
kind type;
|
||||||
|
spacing space;
|
||||||
|
location pos;
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
token(kind type, spacing space, location pos) : type{ type }, space{ space }, pos{ pos }, data{} {}
|
||||||
|
token(kind type, spacing space, location pos, std::string data) : type{ type }, space{ space }, pos{ pos }, data{ std::move(data) } {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
@ -10,6 +10,11 @@
|
|||||||
#include "assembly.hpp"
|
#include "assembly.hpp"
|
||||||
#include "location.hpp"
|
#include "location.hpp"
|
||||||
#include "exception.hpp"
|
#include "exception.hpp"
|
||||||
|
#include "lookahead.hpp"
|
||||||
|
#include "directive.hpp"
|
||||||
|
#include "space.hpp"
|
||||||
|
#include "token.hpp"
|
||||||
|
#include "define.hpp"
|
||||||
#include "ast.hpp"
|
#include "ast.hpp"
|
||||||
|
|
||||||
namespace xsk::gsc
|
namespace xsk::gsc
|
||||||
|
2896
src/gsc/parser.cpp
2896
src/gsc/parser.cpp
File diff suppressed because it is too large
Load Diff
@ -45,14 +45,14 @@
|
|||||||
#ifndef YY_GSC_PARSER_HPP_INCLUDED
|
#ifndef YY_GSC_PARSER_HPP_INCLUDED
|
||||||
# define YY_GSC_PARSER_HPP_INCLUDED
|
# define YY_GSC_PARSER_HPP_INCLUDED
|
||||||
// "%code requires" blocks.
|
// "%code requires" blocks.
|
||||||
#line 30 "parser.ypp"
|
#line 31 "parser.ypp"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable:4065)
|
#pragma warning(disable:4065)
|
||||||
#pragma warning(disable:4127)
|
#pragma warning(disable:4127)
|
||||||
#endif
|
#endif
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
namespace xsk::gsc { class lexer; }
|
namespace xsk::gsc { class preprocessor; }
|
||||||
|
|
||||||
#line 58 "parser.hpp"
|
#line 58 "parser.hpp"
|
||||||
|
|
||||||
@ -706,118 +706,112 @@ namespace xsk { namespace gsc {
|
|||||||
GSCEOF = 0, // "end of file"
|
GSCEOF = 0, // "end of file"
|
||||||
GSCerror = 1, // error
|
GSCerror = 1, // error
|
||||||
GSCUNDEF = 2, // "invalid token"
|
GSCUNDEF = 2, // "invalid token"
|
||||||
SH_DEFINE = 3, // "#define"
|
HASH = 3, // "#"
|
||||||
SH_UNDEF = 4, // "#undef"
|
DEVBEGIN = 4, // "/#"
|
||||||
SH_IFDEF = 5, // "#ifdef"
|
DEVEND = 5, // "#/"
|
||||||
SH_IFNDEF = 6, // "#ifndef"
|
INLINE = 6, // "#inline"
|
||||||
SH_IF = 7, // "#if"
|
INCLUDE = 7, // "#include"
|
||||||
SH_ELIF = 8, // "#elif"
|
USINGTREE = 8, // "#using_animtree"
|
||||||
SH_ELSE = 9, // "#else"
|
ANIMTREE = 9, // "#animtree"
|
||||||
SH_ENDIF = 10, // "#endif"
|
ENDON = 10, // "endon"
|
||||||
DEVBEGIN = 11, // "/#"
|
NOTIFY = 11, // "notify"
|
||||||
DEVEND = 12, // "#/"
|
WAIT = 12, // "wait"
|
||||||
INLINE = 13, // "#inline"
|
WAITTILL = 13, // "waittill"
|
||||||
INCLUDE = 14, // "#include"
|
WAITTILLMATCH = 14, // "waittillmatch"
|
||||||
USINGTREE = 15, // "#using_animtree"
|
WAITTILLFRAMEEND = 15, // "waittillframeend"
|
||||||
ANIMTREE = 16, // "#animtree"
|
WAITFRAME = 16, // "waitframe"
|
||||||
ENDON = 17, // "endon"
|
IF = 17, // "if"
|
||||||
NOTIFY = 18, // "notify"
|
ELSE = 18, // "else"
|
||||||
WAIT = 19, // "wait"
|
DO = 19, // "do"
|
||||||
WAITTILL = 20, // "waittill"
|
WHILE = 20, // "while"
|
||||||
WAITTILLMATCH = 21, // "waittillmatch"
|
FOR = 21, // "for"
|
||||||
WAITTILLFRAMEEND = 22, // "waittillframeend"
|
FOREACH = 22, // "foreach"
|
||||||
WAITFRAME = 23, // "waitframe"
|
IN = 23, // "in"
|
||||||
IF = 24, // "if"
|
SWITCH = 24, // "switch"
|
||||||
ELSE = 25, // "else"
|
CASE = 25, // "case"
|
||||||
DO = 26, // "do"
|
DEFAULT = 26, // "default"
|
||||||
WHILE = 27, // "while"
|
BREAK = 27, // "break"
|
||||||
FOR = 28, // "for"
|
CONTINUE = 28, // "continue"
|
||||||
FOREACH = 29, // "foreach"
|
RETURN = 29, // "return"
|
||||||
IN = 30, // "in"
|
BREAKPOINT = 30, // "breakpoint"
|
||||||
SWITCH = 31, // "switch"
|
PROFBEGIN = 31, // "prof_begin"
|
||||||
CASE = 32, // "case"
|
PROFEND = 32, // "prof_end"
|
||||||
DEFAULT = 33, // "default"
|
THREAD = 33, // "thread"
|
||||||
BREAK = 34, // "break"
|
CHILDTHREAD = 34, // "childthread"
|
||||||
CONTINUE = 35, // "continue"
|
THISTHREAD = 35, // "thisthread"
|
||||||
RETURN = 36, // "return"
|
CALL = 36, // "call"
|
||||||
BREAKPOINT = 37, // "breakpoint"
|
TRUE = 37, // "true"
|
||||||
PROFBEGIN = 38, // "prof_begin"
|
FALSE = 38, // "false"
|
||||||
PROFEND = 39, // "prof_end"
|
UNDEFINED = 39, // "undefined"
|
||||||
THREAD = 40, // "thread"
|
SIZE = 40, // "size"
|
||||||
CHILDTHREAD = 41, // "childthread"
|
GAME = 41, // "game"
|
||||||
THISTHREAD = 42, // "thisthread"
|
SELF = 42, // "self"
|
||||||
CALL = 43, // "call"
|
ANIM = 43, // "anim"
|
||||||
TRUE = 44, // "true"
|
LEVEL = 44, // "level"
|
||||||
FALSE = 45, // "false"
|
ISDEFINED = 45, // "isdefined"
|
||||||
UNDEFINED = 46, // "undefined"
|
ISTRUE = 46, // "istrue"
|
||||||
SIZE = 47, // "size"
|
LPAREN = 47, // "("
|
||||||
GAME = 48, // "game"
|
RPAREN = 48, // ")"
|
||||||
SELF = 49, // "self"
|
LBRACE = 49, // "{"
|
||||||
ANIM = 50, // "anim"
|
RBRACE = 50, // "}"
|
||||||
LEVEL = 51, // "level"
|
LBRACKET = 51, // "["
|
||||||
ISDEFINED = 52, // "isdefined"
|
RBRACKET = 52, // "]"
|
||||||
ISTRUE = 53, // "istrue"
|
COMMA = 53, // ","
|
||||||
LPAREN = 54, // "("
|
DOT = 54, // "."
|
||||||
RPAREN = 55, // ")"
|
ELLIPSIS = 55, // "..."
|
||||||
LBRACE = 56, // "{"
|
DOUBLECOLON = 56, // "::"
|
||||||
RBRACE = 57, // "}"
|
COLON = 57, // ":"
|
||||||
LBRACKET = 58, // "["
|
SEMICOLON = 58, // ";"
|
||||||
RBRACKET = 59, // "]"
|
QMARK = 59, // "?"
|
||||||
COMMA = 60, // ","
|
INCREMENT = 60, // "++"
|
||||||
DOT = 61, // "."
|
DECREMENT = 61, // "--"
|
||||||
DOUBLECOLON = 62, // "::"
|
LSHIFT = 62, // "<<"
|
||||||
COLON = 63, // ":"
|
RSHIFT = 63, // ">>"
|
||||||
SEMICOLON = 64, // ";"
|
OR = 64, // "||"
|
||||||
QMARK = 65, // "?"
|
AND = 65, // "&&"
|
||||||
INCREMENT = 66, // "++"
|
EQUALITY = 66, // "=="
|
||||||
DECREMENT = 67, // "--"
|
INEQUALITY = 67, // "!="
|
||||||
LSHIFT = 68, // "<<"
|
LESS_EQUAL = 68, // "<="
|
||||||
RSHIFT = 69, // ">>"
|
GREATER_EQUAL = 69, // ">="
|
||||||
OR = 70, // "||"
|
LESS = 70, // "<"
|
||||||
AND = 71, // "&&"
|
GREATER = 71, // ">"
|
||||||
EQUALITY = 72, // "=="
|
NOT = 72, // "!"
|
||||||
INEQUALITY = 73, // "!="
|
COMPLEMENT = 73, // "~"
|
||||||
LESS_EQUAL = 74, // "<="
|
ASSIGN = 74, // "="
|
||||||
GREATER_EQUAL = 75, // ">="
|
ASSIGN_ADD = 75, // "+="
|
||||||
LESS = 76, // "<"
|
ASSIGN_SUB = 76, // "-="
|
||||||
GREATER = 77, // ">"
|
ASSIGN_MUL = 77, // "*="
|
||||||
NOT = 78, // "!"
|
ASSIGN_DIV = 78, // "/="
|
||||||
COMPLEMENT = 79, // "~"
|
ASSIGN_MOD = 79, // "%="
|
||||||
ASSIGN = 80, // "="
|
ASSIGN_BW_OR = 80, // "|="
|
||||||
ASSIGN_ADD = 81, // "+="
|
ASSIGN_BW_AND = 81, // "&="
|
||||||
ASSIGN_SUB = 82, // "-="
|
ASSIGN_BW_EXOR = 82, // "^="
|
||||||
ASSIGN_MUL = 83, // "*="
|
ASSIGN_RSHIFT = 83, // ">>="
|
||||||
ASSIGN_DIV = 84, // "/="
|
ASSIGN_LSHIFT = 84, // "<<="
|
||||||
ASSIGN_MOD = 85, // "%="
|
BITWISE_OR = 85, // "|"
|
||||||
ASSIGN_BW_OR = 86, // "|="
|
BITWISE_AND = 86, // "&"
|
||||||
ASSIGN_BW_AND = 87, // "&="
|
BITWISE_EXOR = 87, // "^"
|
||||||
ASSIGN_BW_EXOR = 88, // "^="
|
ADD = 88, // "+"
|
||||||
ASSIGN_RSHIFT = 89, // ">>="
|
SUB = 89, // "-"
|
||||||
ASSIGN_LSHIFT = 90, // "<<="
|
MUL = 90, // "*"
|
||||||
BITWISE_OR = 91, // "|"
|
DIV = 91, // "/"
|
||||||
BITWISE_AND = 92, // "&"
|
MOD = 92, // "%"
|
||||||
BITWISE_EXOR = 93, // "^"
|
PATH = 93, // "path"
|
||||||
ADD = 94, // "+"
|
IDENTIFIER = 94, // "identifier"
|
||||||
SUB = 95, // "-"
|
STRING = 95, // "string literal"
|
||||||
MUL = 96, // "*"
|
ISTRING = 96, // "localized string"
|
||||||
DIV = 97, // "/"
|
FLOAT = 97, // "float"
|
||||||
MOD = 98, // "%"
|
INTEGER = 98, // "integer"
|
||||||
PATH = 99, // "path"
|
SIZEOF = 99, // SIZEOF
|
||||||
IDENTIFIER = 100, // "identifier"
|
ADD_ARRAY = 100, // ADD_ARRAY
|
||||||
STRING = 101, // "string literal"
|
THEN = 101, // THEN
|
||||||
ISTRING = 102, // "localized string"
|
TERN = 102, // TERN
|
||||||
FLOAT = 103, // "float"
|
NEG = 103, // NEG
|
||||||
INTEGER = 104, // "integer"
|
ANIMREF = 104, // ANIMREF
|
||||||
SIZEOF = 105, // SIZEOF
|
PREINC = 105, // PREINC
|
||||||
ADD_ARRAY = 106, // ADD_ARRAY
|
PREDEC = 106, // PREDEC
|
||||||
THEN = 107, // THEN
|
POSTINC = 107, // POSTINC
|
||||||
TERN = 108, // TERN
|
POSTDEC = 108 // POSTDEC
|
||||||
NEG = 109, // NEG
|
|
||||||
ANIMREF = 110, // ANIMREF
|
|
||||||
PREINC = 111, // PREINC
|
|
||||||
PREDEC = 112, // PREDEC
|
|
||||||
POSTINC = 113, // POSTINC
|
|
||||||
POSTDEC = 114 // POSTDEC
|
|
||||||
};
|
};
|
||||||
/// Backward compatibility alias (Bison 3.6).
|
/// Backward compatibility alias (Bison 3.6).
|
||||||
typedef token_kind_type yytokentype;
|
typedef token_kind_type yytokentype;
|
||||||
@ -834,211 +828,205 @@ namespace xsk { namespace gsc {
|
|||||||
{
|
{
|
||||||
enum symbol_kind_type
|
enum symbol_kind_type
|
||||||
{
|
{
|
||||||
YYNTOKENS = 115, ///< Number of tokens.
|
YYNTOKENS = 109, ///< Number of tokens.
|
||||||
S_YYEMPTY = -2,
|
S_YYEMPTY = -2,
|
||||||
S_YYEOF = 0, // "end of file"
|
S_YYEOF = 0, // "end of file"
|
||||||
S_YYerror = 1, // error
|
S_YYerror = 1, // error
|
||||||
S_YYUNDEF = 2, // "invalid token"
|
S_YYUNDEF = 2, // "invalid token"
|
||||||
S_SH_DEFINE = 3, // "#define"
|
S_HASH = 3, // "#"
|
||||||
S_SH_UNDEF = 4, // "#undef"
|
S_DEVBEGIN = 4, // "/#"
|
||||||
S_SH_IFDEF = 5, // "#ifdef"
|
S_DEVEND = 5, // "#/"
|
||||||
S_SH_IFNDEF = 6, // "#ifndef"
|
S_INLINE = 6, // "#inline"
|
||||||
S_SH_IF = 7, // "#if"
|
S_INCLUDE = 7, // "#include"
|
||||||
S_SH_ELIF = 8, // "#elif"
|
S_USINGTREE = 8, // "#using_animtree"
|
||||||
S_SH_ELSE = 9, // "#else"
|
S_ANIMTREE = 9, // "#animtree"
|
||||||
S_SH_ENDIF = 10, // "#endif"
|
S_ENDON = 10, // "endon"
|
||||||
S_DEVBEGIN = 11, // "/#"
|
S_NOTIFY = 11, // "notify"
|
||||||
S_DEVEND = 12, // "#/"
|
S_WAIT = 12, // "wait"
|
||||||
S_INLINE = 13, // "#inline"
|
S_WAITTILL = 13, // "waittill"
|
||||||
S_INCLUDE = 14, // "#include"
|
S_WAITTILLMATCH = 14, // "waittillmatch"
|
||||||
S_USINGTREE = 15, // "#using_animtree"
|
S_WAITTILLFRAMEEND = 15, // "waittillframeend"
|
||||||
S_ANIMTREE = 16, // "#animtree"
|
S_WAITFRAME = 16, // "waitframe"
|
||||||
S_ENDON = 17, // "endon"
|
S_IF = 17, // "if"
|
||||||
S_NOTIFY = 18, // "notify"
|
S_ELSE = 18, // "else"
|
||||||
S_WAIT = 19, // "wait"
|
S_DO = 19, // "do"
|
||||||
S_WAITTILL = 20, // "waittill"
|
S_WHILE = 20, // "while"
|
||||||
S_WAITTILLMATCH = 21, // "waittillmatch"
|
S_FOR = 21, // "for"
|
||||||
S_WAITTILLFRAMEEND = 22, // "waittillframeend"
|
S_FOREACH = 22, // "foreach"
|
||||||
S_WAITFRAME = 23, // "waitframe"
|
S_IN = 23, // "in"
|
||||||
S_IF = 24, // "if"
|
S_SWITCH = 24, // "switch"
|
||||||
S_ELSE = 25, // "else"
|
S_CASE = 25, // "case"
|
||||||
S_DO = 26, // "do"
|
S_DEFAULT = 26, // "default"
|
||||||
S_WHILE = 27, // "while"
|
S_BREAK = 27, // "break"
|
||||||
S_FOR = 28, // "for"
|
S_CONTINUE = 28, // "continue"
|
||||||
S_FOREACH = 29, // "foreach"
|
S_RETURN = 29, // "return"
|
||||||
S_IN = 30, // "in"
|
S_BREAKPOINT = 30, // "breakpoint"
|
||||||
S_SWITCH = 31, // "switch"
|
S_PROFBEGIN = 31, // "prof_begin"
|
||||||
S_CASE = 32, // "case"
|
S_PROFEND = 32, // "prof_end"
|
||||||
S_DEFAULT = 33, // "default"
|
S_THREAD = 33, // "thread"
|
||||||
S_BREAK = 34, // "break"
|
S_CHILDTHREAD = 34, // "childthread"
|
||||||
S_CONTINUE = 35, // "continue"
|
S_THISTHREAD = 35, // "thisthread"
|
||||||
S_RETURN = 36, // "return"
|
S_CALL = 36, // "call"
|
||||||
S_BREAKPOINT = 37, // "breakpoint"
|
S_TRUE = 37, // "true"
|
||||||
S_PROFBEGIN = 38, // "prof_begin"
|
S_FALSE = 38, // "false"
|
||||||
S_PROFEND = 39, // "prof_end"
|
S_UNDEFINED = 39, // "undefined"
|
||||||
S_THREAD = 40, // "thread"
|
S_SIZE = 40, // "size"
|
||||||
S_CHILDTHREAD = 41, // "childthread"
|
S_GAME = 41, // "game"
|
||||||
S_THISTHREAD = 42, // "thisthread"
|
S_SELF = 42, // "self"
|
||||||
S_CALL = 43, // "call"
|
S_ANIM = 43, // "anim"
|
||||||
S_TRUE = 44, // "true"
|
S_LEVEL = 44, // "level"
|
||||||
S_FALSE = 45, // "false"
|
S_ISDEFINED = 45, // "isdefined"
|
||||||
S_UNDEFINED = 46, // "undefined"
|
S_ISTRUE = 46, // "istrue"
|
||||||
S_SIZE = 47, // "size"
|
S_LPAREN = 47, // "("
|
||||||
S_GAME = 48, // "game"
|
S_RPAREN = 48, // ")"
|
||||||
S_SELF = 49, // "self"
|
S_LBRACE = 49, // "{"
|
||||||
S_ANIM = 50, // "anim"
|
S_RBRACE = 50, // "}"
|
||||||
S_LEVEL = 51, // "level"
|
S_LBRACKET = 51, // "["
|
||||||
S_ISDEFINED = 52, // "isdefined"
|
S_RBRACKET = 52, // "]"
|
||||||
S_ISTRUE = 53, // "istrue"
|
S_COMMA = 53, // ","
|
||||||
S_LPAREN = 54, // "("
|
S_DOT = 54, // "."
|
||||||
S_RPAREN = 55, // ")"
|
S_ELLIPSIS = 55, // "..."
|
||||||
S_LBRACE = 56, // "{"
|
S_DOUBLECOLON = 56, // "::"
|
||||||
S_RBRACE = 57, // "}"
|
S_COLON = 57, // ":"
|
||||||
S_LBRACKET = 58, // "["
|
S_SEMICOLON = 58, // ";"
|
||||||
S_RBRACKET = 59, // "]"
|
S_QMARK = 59, // "?"
|
||||||
S_COMMA = 60, // ","
|
S_INCREMENT = 60, // "++"
|
||||||
S_DOT = 61, // "."
|
S_DECREMENT = 61, // "--"
|
||||||
S_DOUBLECOLON = 62, // "::"
|
S_LSHIFT = 62, // "<<"
|
||||||
S_COLON = 63, // ":"
|
S_RSHIFT = 63, // ">>"
|
||||||
S_SEMICOLON = 64, // ";"
|
S_OR = 64, // "||"
|
||||||
S_QMARK = 65, // "?"
|
S_AND = 65, // "&&"
|
||||||
S_INCREMENT = 66, // "++"
|
S_EQUALITY = 66, // "=="
|
||||||
S_DECREMENT = 67, // "--"
|
S_INEQUALITY = 67, // "!="
|
||||||
S_LSHIFT = 68, // "<<"
|
S_LESS_EQUAL = 68, // "<="
|
||||||
S_RSHIFT = 69, // ">>"
|
S_GREATER_EQUAL = 69, // ">="
|
||||||
S_OR = 70, // "||"
|
S_LESS = 70, // "<"
|
||||||
S_AND = 71, // "&&"
|
S_GREATER = 71, // ">"
|
||||||
S_EQUALITY = 72, // "=="
|
S_NOT = 72, // "!"
|
||||||
S_INEQUALITY = 73, // "!="
|
S_COMPLEMENT = 73, // "~"
|
||||||
S_LESS_EQUAL = 74, // "<="
|
S_ASSIGN = 74, // "="
|
||||||
S_GREATER_EQUAL = 75, // ">="
|
S_ASSIGN_ADD = 75, // "+="
|
||||||
S_LESS = 76, // "<"
|
S_ASSIGN_SUB = 76, // "-="
|
||||||
S_GREATER = 77, // ">"
|
S_ASSIGN_MUL = 77, // "*="
|
||||||
S_NOT = 78, // "!"
|
S_ASSIGN_DIV = 78, // "/="
|
||||||
S_COMPLEMENT = 79, // "~"
|
S_ASSIGN_MOD = 79, // "%="
|
||||||
S_ASSIGN = 80, // "="
|
S_ASSIGN_BW_OR = 80, // "|="
|
||||||
S_ASSIGN_ADD = 81, // "+="
|
S_ASSIGN_BW_AND = 81, // "&="
|
||||||
S_ASSIGN_SUB = 82, // "-="
|
S_ASSIGN_BW_EXOR = 82, // "^="
|
||||||
S_ASSIGN_MUL = 83, // "*="
|
S_ASSIGN_RSHIFT = 83, // ">>="
|
||||||
S_ASSIGN_DIV = 84, // "/="
|
S_ASSIGN_LSHIFT = 84, // "<<="
|
||||||
S_ASSIGN_MOD = 85, // "%="
|
S_BITWISE_OR = 85, // "|"
|
||||||
S_ASSIGN_BW_OR = 86, // "|="
|
S_BITWISE_AND = 86, // "&"
|
||||||
S_ASSIGN_BW_AND = 87, // "&="
|
S_BITWISE_EXOR = 87, // "^"
|
||||||
S_ASSIGN_BW_EXOR = 88, // "^="
|
S_ADD = 88, // "+"
|
||||||
S_ASSIGN_RSHIFT = 89, // ">>="
|
S_SUB = 89, // "-"
|
||||||
S_ASSIGN_LSHIFT = 90, // "<<="
|
S_MUL = 90, // "*"
|
||||||
S_BITWISE_OR = 91, // "|"
|
S_DIV = 91, // "/"
|
||||||
S_BITWISE_AND = 92, // "&"
|
S_MOD = 92, // "%"
|
||||||
S_BITWISE_EXOR = 93, // "^"
|
S_PATH = 93, // "path"
|
||||||
S_ADD = 94, // "+"
|
S_IDENTIFIER = 94, // "identifier"
|
||||||
S_SUB = 95, // "-"
|
S_STRING = 95, // "string literal"
|
||||||
S_MUL = 96, // "*"
|
S_ISTRING = 96, // "localized string"
|
||||||
S_DIV = 97, // "/"
|
S_FLOAT = 97, // "float"
|
||||||
S_MOD = 98, // "%"
|
S_INTEGER = 98, // "integer"
|
||||||
S_PATH = 99, // "path"
|
S_SIZEOF = 99, // SIZEOF
|
||||||
S_IDENTIFIER = 100, // "identifier"
|
S_ADD_ARRAY = 100, // ADD_ARRAY
|
||||||
S_STRING = 101, // "string literal"
|
S_THEN = 101, // THEN
|
||||||
S_ISTRING = 102, // "localized string"
|
S_TERN = 102, // TERN
|
||||||
S_FLOAT = 103, // "float"
|
S_NEG = 103, // NEG
|
||||||
S_INTEGER = 104, // "integer"
|
S_ANIMREF = 104, // ANIMREF
|
||||||
S_SIZEOF = 105, // SIZEOF
|
S_PREINC = 105, // PREINC
|
||||||
S_ADD_ARRAY = 106, // ADD_ARRAY
|
S_PREDEC = 106, // PREDEC
|
||||||
S_THEN = 107, // THEN
|
S_POSTINC = 107, // POSTINC
|
||||||
S_TERN = 108, // TERN
|
S_POSTDEC = 108, // POSTDEC
|
||||||
S_NEG = 109, // NEG
|
S_YYACCEPT = 109, // $accept
|
||||||
S_ANIMREF = 110, // ANIMREF
|
S_root = 110, // root
|
||||||
S_PREINC = 111, // PREINC
|
S_program = 111, // program
|
||||||
S_PREDEC = 112, // PREDEC
|
S_inline = 112, // inline
|
||||||
S_POSTINC = 113, // POSTINC
|
S_include = 113, // include
|
||||||
S_POSTDEC = 114, // POSTDEC
|
S_declaration = 114, // declaration
|
||||||
S_YYACCEPT = 115, // $accept
|
S_decl_usingtree = 115, // decl_usingtree
|
||||||
S_root = 116, // root
|
S_decl_function = 116, // decl_function
|
||||||
S_program = 117, // program
|
S_stmt = 117, // stmt
|
||||||
S_inline = 118, // inline
|
S_stmt_or_dev = 118, // stmt_or_dev
|
||||||
S_include = 119, // include
|
S_stmt_list = 119, // stmt_list
|
||||||
S_declaration = 120, // declaration
|
S_stmt_or_dev_list = 120, // stmt_or_dev_list
|
||||||
S_decl_usingtree = 121, // decl_usingtree
|
S_stmt_dev = 121, // stmt_dev
|
||||||
S_decl_function = 122, // decl_function
|
S_stmt_comp = 122, // stmt_comp
|
||||||
S_stmt = 123, // stmt
|
S_stmt_expr = 123, // stmt_expr
|
||||||
S_stmt_or_dev = 124, // stmt_or_dev
|
S_stmt_call = 124, // stmt_call
|
||||||
S_stmt_list = 125, // stmt_list
|
S_stmt_assign = 125, // stmt_assign
|
||||||
S_stmt_or_dev_list = 126, // stmt_or_dev_list
|
S_stmt_endon = 126, // stmt_endon
|
||||||
S_stmt_dev = 127, // stmt_dev
|
S_stmt_notify = 127, // stmt_notify
|
||||||
S_stmt_comp = 128, // stmt_comp
|
S_stmt_wait = 128, // stmt_wait
|
||||||
S_stmt_expr = 129, // stmt_expr
|
S_stmt_waittill = 129, // stmt_waittill
|
||||||
S_stmt_call = 130, // stmt_call
|
S_stmt_waittillmatch = 130, // stmt_waittillmatch
|
||||||
S_stmt_assign = 131, // stmt_assign
|
S_stmt_waittillframeend = 131, // stmt_waittillframeend
|
||||||
S_stmt_endon = 132, // stmt_endon
|
S_stmt_waitframe = 132, // stmt_waitframe
|
||||||
S_stmt_notify = 133, // stmt_notify
|
S_stmt_if = 133, // stmt_if
|
||||||
S_stmt_wait = 134, // stmt_wait
|
S_stmt_ifelse = 134, // stmt_ifelse
|
||||||
S_stmt_waittill = 135, // stmt_waittill
|
S_stmt_while = 135, // stmt_while
|
||||||
S_stmt_waittillmatch = 136, // stmt_waittillmatch
|
S_stmt_dowhile = 136, // stmt_dowhile
|
||||||
S_stmt_waittillframeend = 137, // stmt_waittillframeend
|
S_stmt_for = 137, // stmt_for
|
||||||
S_stmt_waitframe = 138, // stmt_waitframe
|
S_stmt_foreach = 138, // stmt_foreach
|
||||||
S_stmt_if = 139, // stmt_if
|
S_stmt_switch = 139, // stmt_switch
|
||||||
S_stmt_ifelse = 140, // stmt_ifelse
|
S_stmt_case = 140, // stmt_case
|
||||||
S_stmt_while = 141, // stmt_while
|
S_stmt_default = 141, // stmt_default
|
||||||
S_stmt_dowhile = 142, // stmt_dowhile
|
S_stmt_break = 142, // stmt_break
|
||||||
S_stmt_for = 143, // stmt_for
|
S_stmt_continue = 143, // stmt_continue
|
||||||
S_stmt_foreach = 144, // stmt_foreach
|
S_stmt_return = 144, // stmt_return
|
||||||
S_stmt_switch = 145, // stmt_switch
|
S_stmt_breakpoint = 145, // stmt_breakpoint
|
||||||
S_stmt_case = 146, // stmt_case
|
S_stmt_prof_begin = 146, // stmt_prof_begin
|
||||||
S_stmt_default = 147, // stmt_default
|
S_stmt_prof_end = 147, // stmt_prof_end
|
||||||
S_stmt_break = 148, // stmt_break
|
S_expr = 148, // expr
|
||||||
S_stmt_continue = 149, // stmt_continue
|
S_expr_or_empty = 149, // expr_or_empty
|
||||||
S_stmt_return = 150, // stmt_return
|
S_expr_assign = 150, // expr_assign
|
||||||
S_stmt_breakpoint = 151, // stmt_breakpoint
|
S_expr_increment = 151, // expr_increment
|
||||||
S_stmt_prof_begin = 152, // stmt_prof_begin
|
S_expr_decrement = 152, // expr_decrement
|
||||||
S_stmt_prof_end = 153, // stmt_prof_end
|
S_expr_ternary = 153, // expr_ternary
|
||||||
S_expr = 154, // expr
|
S_expr_binary = 154, // expr_binary
|
||||||
S_expr_or_empty = 155, // expr_or_empty
|
S_expr_primitive = 155, // expr_primitive
|
||||||
S_expr_assign = 156, // expr_assign
|
S_expr_complement = 156, // expr_complement
|
||||||
S_expr_increment = 157, // expr_increment
|
S_expr_negate = 157, // expr_negate
|
||||||
S_expr_decrement = 158, // expr_decrement
|
S_expr_not = 158, // expr_not
|
||||||
S_expr_ternary = 159, // expr_ternary
|
S_expr_call = 159, // expr_call
|
||||||
S_expr_binary = 160, // expr_binary
|
S_expr_method = 160, // expr_method
|
||||||
S_expr_primitive = 161, // expr_primitive
|
S_expr_function = 161, // expr_function
|
||||||
S_expr_complement = 162, // expr_complement
|
S_expr_pointer = 162, // expr_pointer
|
||||||
S_expr_negate = 163, // expr_negate
|
S_expr_add_array = 163, // expr_add_array
|
||||||
S_expr_not = 164, // expr_not
|
S_expr_parameters = 164, // expr_parameters
|
||||||
S_expr_call = 165, // expr_call
|
S_expr_arguments = 165, // expr_arguments
|
||||||
S_expr_method = 166, // expr_method
|
S_expr_arguments_no_empty = 166, // expr_arguments_no_empty
|
||||||
S_expr_function = 167, // expr_function
|
S_expr_isdefined = 167, // expr_isdefined
|
||||||
S_expr_pointer = 168, // expr_pointer
|
S_expr_istrue = 168, // expr_istrue
|
||||||
S_expr_add_array = 169, // expr_add_array
|
S_expr_reference = 169, // expr_reference
|
||||||
S_expr_parameters = 170, // expr_parameters
|
S_expr_tuple = 170, // expr_tuple
|
||||||
S_expr_arguments = 171, // expr_arguments
|
S_expr_tuple_arguments = 171, // expr_tuple_arguments
|
||||||
S_expr_arguments_no_empty = 172, // expr_arguments_no_empty
|
S_expr_tuple_types = 172, // expr_tuple_types
|
||||||
S_expr_isdefined = 173, // expr_isdefined
|
S_expr_array = 173, // expr_array
|
||||||
S_expr_istrue = 174, // expr_istrue
|
S_expr_field = 174, // expr_field
|
||||||
S_expr_reference = 175, // expr_reference
|
S_expr_size = 175, // expr_size
|
||||||
S_expr_tuple = 176, // expr_tuple
|
S_expr_paren = 176, // expr_paren
|
||||||
S_expr_tuple_arguments = 177, // expr_tuple_arguments
|
S_expr_object = 177, // expr_object
|
||||||
S_expr_tuple_types = 178, // expr_tuple_types
|
S_expr_thisthread = 178, // expr_thisthread
|
||||||
S_expr_array = 179, // expr_array
|
S_expr_empty_array = 179, // expr_empty_array
|
||||||
S_expr_field = 180, // expr_field
|
S_expr_undefined = 180, // expr_undefined
|
||||||
S_expr_size = 181, // expr_size
|
S_expr_game = 181, // expr_game
|
||||||
S_expr_paren = 182, // expr_paren
|
S_expr_self = 182, // expr_self
|
||||||
S_expr_object = 183, // expr_object
|
S_expr_anim = 183, // expr_anim
|
||||||
S_expr_thisthread = 184, // expr_thisthread
|
S_expr_level = 184, // expr_level
|
||||||
S_expr_empty_array = 185, // expr_empty_array
|
S_expr_animation = 185, // expr_animation
|
||||||
S_expr_undefined = 186, // expr_undefined
|
S_expr_animtree = 186, // expr_animtree
|
||||||
S_expr_game = 187, // expr_game
|
S_expr_identifier_nosize = 187, // expr_identifier_nosize
|
||||||
S_expr_self = 188, // expr_self
|
S_expr_identifier = 188, // expr_identifier
|
||||||
S_expr_anim = 189, // expr_anim
|
S_expr_path = 189, // expr_path
|
||||||
S_expr_level = 190, // expr_level
|
S_expr_istring = 190, // expr_istring
|
||||||
S_expr_animation = 191, // expr_animation
|
S_expr_string = 191, // expr_string
|
||||||
S_expr_animtree = 192, // expr_animtree
|
S_expr_vector = 192, // expr_vector
|
||||||
S_expr_identifier_nosize = 193, // expr_identifier_nosize
|
S_expr_float = 193, // expr_float
|
||||||
S_expr_identifier = 194, // expr_identifier
|
S_expr_integer = 194, // expr_integer
|
||||||
S_expr_path = 195, // expr_path
|
S_expr_false = 195, // expr_false
|
||||||
S_expr_istring = 196, // expr_istring
|
S_expr_true = 196 // expr_true
|
||||||
S_expr_string = 197, // expr_string
|
|
||||||
S_expr_vector = 198, // expr_vector
|
|
||||||
S_expr_float = 199, // expr_float
|
|
||||||
S_expr_integer = 200, // expr_integer
|
|
||||||
S_expr_false = 201, // expr_false
|
|
||||||
S_expr_true = 202 // expr_true
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2841,7 +2829,7 @@ switch (yykind)
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Build a parser object.
|
/// Build a parser object.
|
||||||
parser (xsk::gsc::context const* ctx__yyarg, xsk::gsc::lexer& lexer_yyarg, xsk::gsc::program::ptr& ast_yyarg, std::uint32_t index_yyarg);
|
parser (xsk::gsc::context const* ctx__yyarg, xsk::gsc::preprocessor& ppr_yyarg, xsk::gsc::program::ptr& ast_yyarg, std::uint32_t index_yyarg);
|
||||||
virtual ~parser ();
|
virtual ~parser ();
|
||||||
|
|
||||||
#if 201103L <= YY_CPLUSPLUS
|
#if 201103L <= YY_CPLUSPLUS
|
||||||
@ -2934,121 +2922,16 @@ switch (yykind)
|
|||||||
#if 201103L <= YY_CPLUSPLUS
|
#if 201103L <= YY_CPLUSPLUS
|
||||||
static
|
static
|
||||||
symbol_type
|
symbol_type
|
||||||
make_SH_DEFINE (location_type l)
|
make_HASH (location_type l)
|
||||||
{
|
{
|
||||||
return symbol_type (token::SH_DEFINE, std::move (l));
|
return symbol_type (token::HASH, std::move (l));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static
|
static
|
||||||
symbol_type
|
symbol_type
|
||||||
make_SH_DEFINE (const location_type& l)
|
make_HASH (const location_type& l)
|
||||||
{
|
{
|
||||||
return symbol_type (token::SH_DEFINE, l);
|
return symbol_type (token::HASH, 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
|
#endif
|
||||||
#if 201103L <= YY_CPLUSPLUS
|
#if 201103L <= YY_CPLUSPLUS
|
||||||
@ -3816,6 +3699,21 @@ switch (yykind)
|
|||||||
return symbol_type (token::DOT, l);
|
return symbol_type (token::DOT, l);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if 201103L <= YY_CPLUSPLUS
|
||||||
|
static
|
||||||
|
symbol_type
|
||||||
|
make_ELLIPSIS (location_type l)
|
||||||
|
{
|
||||||
|
return symbol_type (token::ELLIPSIS, std::move (l));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static
|
||||||
|
symbol_type
|
||||||
|
make_ELLIPSIS (const location_type& l)
|
||||||
|
{
|
||||||
|
return symbol_type (token::ELLIPSIS, l);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if 201103L <= YY_CPLUSPLUS
|
#if 201103L <= YY_CPLUSPLUS
|
||||||
static
|
static
|
||||||
symbol_type
|
symbol_type
|
||||||
@ -4955,7 +4853,7 @@ switch (yykind)
|
|||||||
/// Constants.
|
/// Constants.
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
yylast_ = 2411, ///< Last index in yytable_.
|
yylast_ = 2289, ///< Last index in yytable_.
|
||||||
yynnts_ = 88, ///< Number of nonterminal symbols.
|
yynnts_ = 88, ///< Number of nonterminal symbols.
|
||||||
yyfinal_ = 21 ///< Termination state number.
|
yyfinal_ = 21 ///< Termination state number.
|
||||||
};
|
};
|
||||||
@ -4963,7 +4861,7 @@ switch (yykind)
|
|||||||
|
|
||||||
// User arguments.
|
// User arguments.
|
||||||
xsk::gsc::context const* ctx_;
|
xsk::gsc::context const* ctx_;
|
||||||
xsk::gsc::lexer& lexer;
|
xsk::gsc::preprocessor& ppr;
|
||||||
xsk::gsc::program::ptr& ast;
|
xsk::gsc::program::ptr& ast;
|
||||||
std::uint32_t index;
|
std::uint32_t index;
|
||||||
|
|
||||||
@ -5691,7 +5589,7 @@ switch (yykind)
|
|||||||
|
|
||||||
#line 13 "parser.ypp"
|
#line 13 "parser.ypp"
|
||||||
} } // xsk::gsc
|
} } // xsk::gsc
|
||||||
#line 5695 "parser.hpp"
|
#line 5593 "parser.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1080
src/gsc/preprocessor.cpp
Normal file
1080
src/gsc/preprocessor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
85
src/gsc/preprocessor.hpp
Normal file
85
src/gsc/preprocessor.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2023 xensik. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a GNU GPLv3 license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "misc/types.hpp"
|
||||||
|
#include "lexer.hpp"
|
||||||
|
|
||||||
|
namespace xsk::gsc
|
||||||
|
{
|
||||||
|
|
||||||
|
class preprocessor
|
||||||
|
{
|
||||||
|
context const* ctx_;
|
||||||
|
std::stack<lexer> lexer_;
|
||||||
|
std::stack<directive> indents_;
|
||||||
|
std::vector<std::string> includes_;
|
||||||
|
std::unordered_map<std::string_view, directive::kind> directives_;
|
||||||
|
std::unordered_map<std::string, define> defines_;
|
||||||
|
std::set<std::string> reject_;
|
||||||
|
std::deque<token> tokens_;
|
||||||
|
std::vector<token> expr_;
|
||||||
|
usize curr_expr_;
|
||||||
|
u32 expand_;
|
||||||
|
u32 skip_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
preprocessor(context const* ctx, std::string const& name, char const* data, usize size);
|
||||||
|
auto process() -> token;
|
||||||
|
auto push_header(std::string const& file) -> void;
|
||||||
|
auto pop_header() -> void;
|
||||||
|
auto ban_header(location const& loc) -> void;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto skip_line() -> void;
|
||||||
|
auto next_token() -> token;
|
||||||
|
auto read_token() -> token;
|
||||||
|
auto read_directive(token& tok) -> void;
|
||||||
|
auto read_directive_if(token& tok) -> void;
|
||||||
|
auto read_directive_ifdef(token& tok) -> void;
|
||||||
|
auto read_directive_ifndef(token& tok) -> void;
|
||||||
|
auto read_directive_elif(token& tok) -> void;
|
||||||
|
auto read_directive_elifdef(token& tok) -> void;
|
||||||
|
auto read_directive_elifndef(token& tok) -> void;
|
||||||
|
auto read_directive_else(token& tok) -> void;
|
||||||
|
auto read_directive_endif(token& tok) -> void;
|
||||||
|
auto read_directive_define(token& tok) -> void;
|
||||||
|
auto read_directive_undef(token& tok) -> void;
|
||||||
|
auto read_directive_pragma(token& tok) -> void;
|
||||||
|
auto read_directive_warning(token& tok) -> void;
|
||||||
|
auto read_directive_error(token& tok) -> void;
|
||||||
|
auto read_directive_line(token& tok) -> void;
|
||||||
|
auto read_directive_include(token& hash, token& name) -> void;
|
||||||
|
auto read_directive_inline(token& hash, token& name) -> void;
|
||||||
|
auto read_directive_usingtree(token& hash, token& name) -> void;
|
||||||
|
auto read_hashtoken(token& hash) -> void;
|
||||||
|
auto read_hashtoken_animtree(token& hash, token& name) -> void;
|
||||||
|
auto expand(token& tok, define& def) -> void;
|
||||||
|
auto expect(token& tok, token::kind expected, spacing space = spacing::none) -> void;
|
||||||
|
auto evaluate() -> bool;
|
||||||
|
auto eval_next() -> token&;
|
||||||
|
auto eval_peek() -> token&;
|
||||||
|
auto eval_prev() -> token&;
|
||||||
|
auto eval_atend() -> bool;
|
||||||
|
auto eval_check(token::kind type) -> bool;
|
||||||
|
auto eval_match(token::kind type) -> bool;
|
||||||
|
auto eval_consume(token::kind type, std::string_view msg);
|
||||||
|
auto eval_expr() -> i32;
|
||||||
|
auto eval_expr_or() -> i32;
|
||||||
|
auto eval_expr_and() -> i32;
|
||||||
|
auto eval_expr_bwor() -> i32;
|
||||||
|
auto eval_expr_bwexor() -> i32;
|
||||||
|
auto eval_expr_bwand() -> i32;
|
||||||
|
auto eval_expr_eq() -> i32;
|
||||||
|
auto eval_expr_lge() -> i32;
|
||||||
|
auto eval_expr_shift() -> i32;
|
||||||
|
auto eval_expr_add() -> i32;
|
||||||
|
auto eval_expr_factor() -> i32;
|
||||||
|
auto eval_expr_unary() -> i32;
|
||||||
|
auto eval_expr_primary() -> i32;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::gsc
|
@ -6,13 +6,14 @@
|
|||||||
#include "stdinc.hpp"
|
#include "stdinc.hpp"
|
||||||
#include "source.hpp"
|
#include "source.hpp"
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "lexer.hpp"
|
#include "preprocessor.hpp"
|
||||||
|
#include "parser.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace xsk::gsc
|
namespace xsk::gsc
|
||||||
{
|
{
|
||||||
|
|
||||||
source::source(context const* ctx) : ctx_{ ctx }
|
source::source(context const* ctx) : ctx_{ ctx }, indent_{ 0 }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +51,6 @@ auto source::parse_assembly(u8 const* data, usize size) -> assembly::ptr
|
|||||||
func->index = index;
|
func->index = index;
|
||||||
func->name = line.substr(4);
|
func->name = line.substr(4);
|
||||||
func->id = ctx_->token_id(func->name);
|
func->id = ctx_->token_id(func->name);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (line.substr(0, 4) == "end:")
|
else if (line.substr(0, 4) == "end:")
|
||||||
{
|
{
|
||||||
@ -143,8 +143,8 @@ auto source::parse_program(std::string const& name, std::vector<u8> const& data)
|
|||||||
auto source::parse_program(std::string const& name, u8 const* data, usize size) -> program::ptr
|
auto source::parse_program(std::string const& name, u8 const* data, usize size) -> program::ptr
|
||||||
{
|
{
|
||||||
auto res = program::ptr{ nullptr };
|
auto res = program::ptr{ nullptr };
|
||||||
auto lxr = lexer{ ctx_, name, reinterpret_cast<char const*>(data), size };
|
auto ppr = preprocessor{ ctx_, name, reinterpret_cast<char const*>(data), size };
|
||||||
auto psr = parser{ ctx_, lxr, res, 0 };
|
auto psr = parser{ ctx_, ppr, res, 0 };
|
||||||
|
|
||||||
if (!psr.parse() && res != nullptr)
|
if (!psr.parse() && res != nullptr)
|
||||||
return res;
|
return res;
|
||||||
@ -341,6 +341,7 @@ auto source::dump_decl_usingtree(decl_usingtree const& dec) -> void
|
|||||||
|
|
||||||
auto source::dump_decl_function(decl_function const& dec) -> void
|
auto source::dump_decl_function(decl_function const& dec) -> void
|
||||||
{
|
{
|
||||||
|
indent_ = 0;
|
||||||
dump_expr_identifier(*dec.name);
|
dump_expr_identifier(*dec.name);
|
||||||
fmt::format_to(std::back_inserter(buf_), "(");
|
fmt::format_to(std::back_inserter(buf_), "(");
|
||||||
dump_expr_parameters(*dec.params);
|
dump_expr_parameters(*dec.params);
|
||||||
@ -567,6 +568,12 @@ auto source::dump_stmt_wait(stmt_wait const& stm) -> void
|
|||||||
dump_expr(stm.time);
|
dump_expr(stm.time);
|
||||||
fmt::format_to(std::back_inserter(buf_), ";");
|
fmt::format_to(std::back_inserter(buf_), ";");
|
||||||
}
|
}
|
||||||
|
else if (stm.time == node::expr_paren)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(buf_), "wait");
|
||||||
|
dump_expr(stm.time);
|
||||||
|
fmt::format_to(std::back_inserter(buf_), ";");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fmt::format_to(std::back_inserter(buf_), "wait(");
|
fmt::format_to(std::back_inserter(buf_), "wait(");
|
||||||
|
@ -12,8 +12,11 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
|
#include <deque>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -31,7 +31,7 @@ namespace xsk
|
|||||||
{
|
{
|
||||||
|
|
||||||
enum class encd { _, source, assembly, binary };
|
enum class encd { _, source, assembly, binary };
|
||||||
enum class mode { _, assemble, disassemble, compile, decompile };
|
enum class mode { _, assemble, disassemble, compile, decompile, parse };
|
||||||
enum class game { _, iw5ps, iw5xb, iw6ps, iw6xb, s1ps, s1xb, iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6 };
|
enum class game { _, iw5ps, iw5xb, iw6ps, iw6xb, s1ps, s1xb, iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6 };
|
||||||
|
|
||||||
std::unordered_map<std::string_view, encd> const exts =
|
std::unordered_map<std::string_view, encd> const exts =
|
||||||
@ -48,6 +48,7 @@ std::unordered_map<std::string_view, mode> const modes =
|
|||||||
{ "disasm", mode::disassemble },
|
{ "disasm", mode::disassemble },
|
||||||
{ "comp", mode::compile },
|
{ "comp", mode::compile },
|
||||||
{ "decomp", mode::decompile },
|
{ "decomp", mode::decompile },
|
||||||
|
{ "parse", mode::parse },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<std::string_view, game> const games =
|
std::unordered_map<std::string_view, game> const games =
|
||||||
@ -359,6 +360,27 @@ auto decompile_file(game game, fs::path file, fs::path rel) -> void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto parse_file(game game, fs::path file, fs::path rel) -> void
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (file.extension() != ".gsc")
|
||||||
|
throw std::runtime_error("expected .gsc file");
|
||||||
|
|
||||||
|
rel = fs::path{ games_rev.at(game) } / rel / file.filename();
|
||||||
|
|
||||||
|
auto data = utils::file::read(file);
|
||||||
|
|
||||||
|
auto prog = contexts[game]->source().parse_program(file.string(), data);
|
||||||
|
utils::file::save(fs::path{ "parsed" } / rel, contexts[game]->source().dump(*prog));
|
||||||
|
fmt::print("parsed {}\n", rel.generic_string());
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
std::cerr << fmt::format("{} at {}\n", e.what(), file.generic_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, std::vector<std::uint8_t>> files;
|
std::unordered_map<std::string, std::vector<std::uint8_t>> files;
|
||||||
|
|
||||||
auto read_file_cb(std::string const& name) -> std::pair<buffer, buffer>
|
auto read_file_cb(std::string const& name) -> std::pair<buffer, buffer>
|
||||||
@ -541,6 +563,7 @@ auto init(game game) -> void
|
|||||||
funcs[mode::disassemble] = disassemble_file;
|
funcs[mode::disassemble] = disassemble_file;
|
||||||
funcs[mode::compile] = compile_file;
|
funcs[mode::compile] = compile_file;
|
||||||
funcs[mode::decompile] = decompile_file;
|
funcs[mode::decompile] = decompile_file;
|
||||||
|
funcs[mode::parse] = parse_file;
|
||||||
|
|
||||||
switch (game)
|
switch (game)
|
||||||
{
|
{
|
||||||
@ -676,6 +699,11 @@ void decompile_file(game game, fs::path const& file, fs::path rel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse_file(game, fs::path const&, fs::path)
|
||||||
|
{
|
||||||
|
std::cerr << fmt::format("not implemented for t6\n");
|
||||||
|
}
|
||||||
|
|
||||||
auto init_t6() -> void
|
auto init_t6() -> void
|
||||||
{
|
{
|
||||||
if (!contexts.contains(game::t6))
|
if (!contexts.contains(game::t6))
|
||||||
@ -691,6 +719,7 @@ auto init(game game) -> void
|
|||||||
funcs[mode::disassemble] = disassemble_file;
|
funcs[mode::disassemble] = disassemble_file;
|
||||||
funcs[mode::compile] = compile_file;
|
funcs[mode::compile] = compile_file;
|
||||||
funcs[mode::decompile] = decompile_file;
|
funcs[mode::decompile] = decompile_file;
|
||||||
|
funcs[mode::parse] = parse_file;
|
||||||
|
|
||||||
switch (game)
|
switch (game)
|
||||||
{
|
{
|
||||||
@ -780,7 +809,7 @@ auto parse_flags(u32 argc, char** argv, game& game, mode& mode, fs::path& path)
|
|||||||
auto print_usage() -> void
|
auto print_usage() -> void
|
||||||
{
|
{
|
||||||
std::cout << "usage: gsc-tool <mode> <game> <path>\n";
|
std::cout << "usage: gsc-tool <mode> <game> <path>\n";
|
||||||
std::cout << "\t* modes: asm, disasm, comp, decomp\n";
|
std::cout << "\t* modes: asm, disasm, comp, decomp, parse\n";
|
||||||
std::cout << "\t* games: iw5ps, iw5xb, iw6ps, iw6xb, s1ps, s1xb, iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6\n";
|
std::cout << "\t* games: iw5ps, iw5xb, iw6ps, iw6xb, s1ps, s1xb, iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6\n";
|
||||||
std::cout << "\t* paths: file or directory (recursive)\n";
|
std::cout << "\t* paths: file or directory (recursive)\n";
|
||||||
std::cin.get();
|
std::cin.get();
|
||||||
|
@ -23,7 +23,8 @@ reader::reader(u8 const* data, u32 size, bool swap) : data_{ data }, size_{ size
|
|||||||
|
|
||||||
template<> auto reader::read() -> i8
|
template<> auto reader::read() -> i8
|
||||||
{
|
{
|
||||||
if (pos_ + 1 > size_) return i8{};
|
if (pos_ + 1 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
auto value = *reinterpret_cast<i8 const*>(data_ + pos_);
|
auto value = *reinterpret_cast<i8 const*>(data_ + pos_);
|
||||||
pos_ += 1;
|
pos_ += 1;
|
||||||
@ -32,7 +33,8 @@ template<> auto reader::read() -> i8
|
|||||||
|
|
||||||
template<> auto reader::read() -> u8
|
template<> auto reader::read() -> u8
|
||||||
{
|
{
|
||||||
if (pos_ + 1 > size_) return u8{};
|
if (pos_ + 1 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
auto value = *reinterpret_cast<u8 const*>(data_ + pos_);
|
auto value = *reinterpret_cast<u8 const*>(data_ + pos_);
|
||||||
pos_ += 1;
|
pos_ += 1;
|
||||||
@ -41,7 +43,8 @@ template<> auto reader::read() -> u8
|
|||||||
|
|
||||||
template<> auto reader::read() -> i16
|
template<> auto reader::read() -> i16
|
||||||
{
|
{
|
||||||
if (pos_ + 2 > size_) return i16{};
|
if (pos_ + 2 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -59,7 +62,8 @@ template<> auto reader::read() -> i16
|
|||||||
|
|
||||||
template<> auto reader::read() -> u16
|
template<> auto reader::read() -> u16
|
||||||
{
|
{
|
||||||
if (pos_ + 2 > size_) return u16{};
|
if (pos_ + 2 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -77,7 +81,8 @@ template<> auto reader::read() -> u16
|
|||||||
|
|
||||||
template<> auto reader::read() -> i32
|
template<> auto reader::read() -> i32
|
||||||
{
|
{
|
||||||
if (pos_ + 4 > size_) return i32{};
|
if (pos_ + 4 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -97,7 +102,8 @@ template<> auto reader::read() -> i32
|
|||||||
|
|
||||||
template<> auto reader::read() -> u32
|
template<> auto reader::read() -> u32
|
||||||
{
|
{
|
||||||
if (pos_ + 4 > size_) return u32{};
|
if (pos_ + 4 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -117,7 +123,8 @@ template<> auto reader::read() -> u32
|
|||||||
|
|
||||||
template<> auto reader::read() -> i64
|
template<> auto reader::read() -> i64
|
||||||
{
|
{
|
||||||
if (pos_ + 8 > size_) return i64{};
|
if (pos_ + 8 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -141,7 +148,8 @@ template<> auto reader::read() -> i64
|
|||||||
|
|
||||||
template<> auto reader::read() -> u64
|
template<> auto reader::read() -> u64
|
||||||
{
|
{
|
||||||
if (pos_ + 8 > size_) return u64{};
|
if (pos_ + 8 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -165,7 +173,8 @@ template<> auto reader::read() -> u64
|
|||||||
|
|
||||||
template<> auto reader::read() -> f32
|
template<> auto reader::read() -> f32
|
||||||
{
|
{
|
||||||
if (pos_ + 4 > size_) return f32{};
|
if (pos_ + 4 > size_)
|
||||||
|
throw std::runtime_error("reader: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -198,7 +207,7 @@ auto reader::read_bytes(u32 pos, u32 count) -> std::string
|
|||||||
|
|
||||||
for (auto i = pos; i < pos + count; i++)
|
for (auto i = pos; i < pos + count; i++)
|
||||||
{
|
{
|
||||||
data += fmt::format("{:02X} ", *reinterpret_cast<u8 const*>(data_ + i));
|
fmt::format_to(std::back_insert_iterator(data), "{:02X} ", *reinterpret_cast<u8 const*>(data_ + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
data.pop_back();
|
data.pop_back();
|
||||||
|
@ -33,7 +33,8 @@ auto writer::clear() -> void
|
|||||||
|
|
||||||
template<> auto writer::write(i8 data) -> void
|
template<> auto writer::write(i8 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 1 > size_) return;
|
if (pos_ + 1 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
*reinterpret_cast<i8*>(data_ + pos_) = data;
|
*reinterpret_cast<i8*>(data_ + pos_) = data;
|
||||||
pos_ += 1;
|
pos_ += 1;
|
||||||
@ -41,7 +42,8 @@ template<> auto writer::write(i8 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(u8 data) -> void
|
template<> auto writer::write(u8 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 1 > size_) return;
|
if (pos_ + 1 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
*reinterpret_cast<u8*>(data_ + pos_) = data;
|
*reinterpret_cast<u8*>(data_ + pos_) = data;
|
||||||
pos_ += 1;
|
pos_ += 1;
|
||||||
@ -49,7 +51,8 @@ template<> auto writer::write(u8 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(i16 data) -> void
|
template<> auto writer::write(i16 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 2 > size_) return;
|
if (pos_ + 2 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -66,7 +69,8 @@ template<> auto writer::write(i16 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(u16 data) -> void
|
template<> auto writer::write(u16 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 2 > size_) return;
|
if (pos_ + 2 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -83,7 +87,8 @@ template<> auto writer::write(u16 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(i32 data) -> void
|
template<> auto writer::write(i32 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 4 > size_) return;
|
if (pos_ + 4 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -102,7 +107,8 @@ template<> auto writer::write(i32 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(u32 data) -> void
|
template<> auto writer::write(u32 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 4 > size_) return;
|
if (pos_ + 4 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -121,7 +127,8 @@ template<> auto writer::write(u32 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(i64 data) -> void
|
template<> auto writer::write(i64 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 8 > size_) return;
|
if (pos_ + 8 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -144,7 +151,8 @@ template<> auto writer::write(i64 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(u64 data) -> void
|
template<> auto writer::write(u64 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 8 > size_) return;
|
if (pos_ + 8 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -167,7 +175,8 @@ template<> auto writer::write(u64 data) -> void
|
|||||||
|
|
||||||
template<> auto writer::write(f32 data) -> void
|
template<> auto writer::write(f32 data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + 4 > size_) return;
|
if (pos_ + 4 > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
if (!swap_)
|
if (!swap_)
|
||||||
{
|
{
|
||||||
@ -186,7 +195,8 @@ template<> auto writer::write(f32 data) -> void
|
|||||||
|
|
||||||
auto writer::write_string(std::string const& data) -> void
|
auto writer::write_string(std::string const& data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + data.size() > size_) return;
|
if (pos_ + data.size() > size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
std::memcpy(reinterpret_cast<void*>(data_ + pos_), data.data(), data.size());
|
std::memcpy(reinterpret_cast<void*>(data_ + pos_), data.data(), data.size());
|
||||||
pos_ += static_cast<u32>(data.size());
|
pos_ += static_cast<u32>(data.size());
|
||||||
@ -194,28 +204,13 @@ auto writer::write_string(std::string const& data) -> void
|
|||||||
|
|
||||||
auto writer::write_cstr(std::string const& data) -> void
|
auto writer::write_cstr(std::string const& data) -> void
|
||||||
{
|
{
|
||||||
if (pos_ + data.size() >= size_) return;
|
if (pos_ + data.size() >= size_)
|
||||||
|
throw std::runtime_error("writer: out of bounds");
|
||||||
|
|
||||||
std::memcpy(reinterpret_cast<void*>(data_ + pos_), data.data(), data.size());
|
std::memcpy(reinterpret_cast<void*>(data_ + pos_), data.data(), data.size());
|
||||||
pos_ += static_cast<u32>(data.size() + 1);
|
pos_ += static_cast<u32>(data.size() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto writer::read_bytes(u32 pos, u32 count) -> std::string
|
|
||||||
{
|
|
||||||
auto data = std::string{};
|
|
||||||
|
|
||||||
data.reserve(count * 3);
|
|
||||||
|
|
||||||
for (auto i = pos; i < pos + count; i++)
|
|
||||||
{
|
|
||||||
data += fmt::format("{:02X} ", *reinterpret_cast<const u8*>(data_ + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
data.pop_back();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto writer::is_avail() -> bool
|
auto writer::is_avail() -> bool
|
||||||
{
|
{
|
||||||
return (pos_ < size_) ? true : false;
|
return (pos_ < size_) ? true : false;
|
||||||
|
@ -28,7 +28,6 @@ public:
|
|||||||
auto write(T data) -> void;
|
auto write(T data) -> void;
|
||||||
auto write_string(std::string const& data) -> void;
|
auto write_string(std::string const& data) -> void;
|
||||||
auto write_cstr(std::string const& data) -> void;
|
auto write_cstr(std::string const& data) -> void;
|
||||||
auto read_bytes(u32 pos, u32 count) -> std::string;
|
|
||||||
auto is_avail() -> bool;
|
auto is_avail() -> bool;
|
||||||
auto seek(u32 size) -> void;
|
auto seek(u32 size) -> void;
|
||||||
auto seek_neg(u32 size) -> void;
|
auto seek_neg(u32 size) -> void;
|
||||||
|
Loading…
Reference in New Issue
Block a user