gsc-tool/gen/iw8/lexer.lpp
2022-01-21 13:31:11 +01:00

243 lines
12 KiB
Plaintext

/* Copyright 2021 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%option outfile="lexer.cpp"
%option header-file="lexer.hpp"
%option prefix="iw8_"
%option reentrant
%option noyywrap batch nounput noinput
%option never-interactive
%option nounistd
%top{
#include "stdafx.hpp"
#include "iw8.hpp"
#include "parser.hpp"
using namespace xsk::gsc;
void iw8_push_header(xsk::gsc::context* ctx, const std::string& file);
void iw8_pop_header(xsk::gsc::context* ctx);
}
%{
#define YY_USER_ACTION ctx->loc.columns(yyleng);
%}
RGX_PATH ([_A-Za-z0-9]+\\)+[_A-Za-z0-9]+
RGX_IDENTIFIER [_A-Za-z][_A-Za-z0-9]*
RGX_STRING \"(?:\\.|[^\"])*?\"|\'(?:\\.|[^\'])*?\'
RGX_COLOR_S #[0-9a-fA-F]{3}
RGX_COLOR_L #[0-9a-fA-F]{6}
RGX_FLT_DEC [0-9]+\.(?:[0-9]*)?f?|\.[0-9]+f?
RGX_INT_OCT 0[1-7][0-7]*
RGX_INT_BIN 0[bB][01]+
RGX_INT_HEX 0[xX][0-9a-fA-F]+
RGX_INT_DEC [0-9]+
RGX_DEFAULT (.|\n)
%x COMMENT_STATE
%x DEV_OFF_STATE
%s DEV_ON_STATE
%%
%{
ctx->loc.step();
%}
[ \t\r] { ctx->loc.step(); }
\n { ctx->loc.lines(yyleng); ctx->loc.step(); }
"//".*
"/*" { BEGIN(COMMENT_STATE); }
<COMMENT_STATE>.
<COMMENT_STATE>\n { ctx->loc.lines(yyleng); ctx->loc.step(); }
<COMMENT_STATE>"*/" { BEGIN(INITIAL); }
<COMMENT_STATE><<EOF>> { throw iw8::parser::syntax_error(ctx->loc, "unmatched multiline comment start ('/*')"); }
<INITIAL>"*/" { throw iw8::parser::syntax_error(ctx->loc, "unmatched multiline comment end ('*/')"); }
<DEV_ON_STATE>"/#" { throw iw8::parser::syntax_error(ctx->loc, "cannot recurse devblock ('/#')"); }
<DEV_ON_STATE>"#/" { BEGIN(INITIAL); return iw8::parser::make_DEVEND(ctx->loc); }
<DEV_ON_STATE><<EOF>> { throw iw8::parser::syntax_error(ctx->loc, "unmatched devblock start ('/#')"); }
"/#" { BEGIN(ctx->mode == xsk::gsc::build::dev ? DEV_ON_STATE : DEV_OFF_STATE); if(ctx->mode == xsk::gsc::build::dev) return iw8::parser::make_DEVBEGIN(ctx->loc); }
<DEV_OFF_STATE>.
<DEV_OFF_STATE>\n { ctx->loc.lines(yyleng); ctx->loc.step(); }
<DEV_OFF_STATE>"#/" { BEGIN(INITIAL); }
<DEV_OFF_STATE><<EOF>> { throw iw8::parser::syntax_error(ctx->loc, "unmatched devblock start ('/#')"); }
<INITIAL>"#/" { throw iw8::parser::syntax_error(ctx->loc, "unmatched devblock end ('#/')"); }
"#inline" { return iw8::parser::make_INLINE(ctx->loc); }
"#include" { return iw8::parser::make_INCLUDE(ctx->loc); }
"#using_animtree" { return iw8::parser::make_USINGTREE(ctx->loc); }
"#animtree" { return iw8::parser::make_ANIMTREE(ctx->loc); }
"endon" { return iw8::parser::make_ENDON(ctx->loc); }
"notify" { return iw8::parser::make_NOTIFY(ctx->loc); }
"wait" { return iw8::parser::make_WAIT(ctx->loc); }
"waittill" { return iw8::parser::make_WAITTILL(ctx->loc); }
"waittillmatch" { return iw8::parser::make_WAITTILLMATCH(ctx->loc); }
"waittillframeend" { return iw8::parser::make_WAITTILLFRAMEEND(ctx->loc); }
"waitframe" { return iw8::parser::make_WAITFRAME(ctx->loc); }
"if" { return iw8::parser::make_IF(ctx->loc); }
"else" { return iw8::parser::make_ELSE(ctx->loc); }
"do" { return iw8::parser::make_DO(ctx->loc); }
"while" { return iw8::parser::make_WHILE(ctx->loc); }
"for" { return iw8::parser::make_FOR(ctx->loc); }
"foreach" { return iw8::parser::make_FOREACH(ctx->loc); }
"in" { return iw8::parser::make_IN(ctx->loc); }
"switch" { return iw8::parser::make_SWITCH(ctx->loc); }
"case" { return iw8::parser::make_CASE(ctx->loc); }
"default" { return iw8::parser::make_DEFAULT(ctx->loc); }
"break" { return iw8::parser::make_BREAK(ctx->loc); }
"continue" { return iw8::parser::make_CONTINUE(ctx->loc); }
"return" { return iw8::parser::make_RETURN(ctx->loc); }
"breakpoint" { return iw8::parser::make_BREAKPOINT(ctx->loc); }
"prof_begin" { return iw8::parser::make_PROFBEGIN(ctx->loc); }
"prof_end" { return iw8::parser::make_PROFEND(ctx->loc); }
"thread" { return iw8::parser::make_THREAD(ctx->loc); }
"childthread" { return iw8::parser::make_CHILDTHREAD(ctx->loc); }
"thisthread" { return iw8::parser::make_THISTHREAD(ctx->loc); }
"call" { return iw8::parser::make_CALL(ctx->loc); }
"true" { return iw8::parser::make_TRUE(ctx->loc); }
"false" { return iw8::parser::make_FALSE(ctx->loc); }
"undefined" { return iw8::parser::make_UNDEFINED(ctx->loc); }
".size" { return iw8::parser::make_SIZE(ctx->loc); }
"game" { return iw8::parser::make_GAME(ctx->loc); }
"self" { return iw8::parser::make_SELF(ctx->loc); }
"anim" { return iw8::parser::make_ANIM(ctx->loc); }
"level" { return iw8::parser::make_LEVEL(ctx->loc); }
(?i:isdefined) { return iw8::parser::make_ISDEFINED(ctx->loc); }
(?i:istrue) { return iw8::parser::make_ISTRUE(ctx->loc); }
\( { return iw8::parser::make_LPAREN(ctx->loc); }
\) { return iw8::parser::make_RPAREN(ctx->loc); }
\{ { return iw8::parser::make_LBRACE(ctx->loc); }
\} { return iw8::parser::make_RBRACE(ctx->loc); }
\[ { return iw8::parser::make_LBRACKET(ctx->loc); }
\] { return iw8::parser::make_RBRACKET(ctx->loc); }
\, { return iw8::parser::make_COMMA(ctx->loc); }
\. { return iw8::parser::make_DOT(ctx->loc); }
\:\: { return iw8::parser::make_DOUBLECOLON(ctx->loc); }
\: { return iw8::parser::make_COLON(ctx->loc); }
\; { return iw8::parser::make_SEMICOLON(ctx->loc); }
\? { return iw8::parser::make_QMARK(ctx->loc); }
\+\+ { return iw8::parser::make_INCREMENT(ctx->loc); }
\-\- { return iw8::parser::make_DECREMENT(ctx->loc); }
\<\<\= { return iw8::parser::make_ASSIGN_LSHIFT(ctx->loc); }
\>\>\= { return iw8::parser::make_ASSIGN_RSHIFT(ctx->loc); }
\<\< { return iw8::parser::make_LSHIFT(ctx->loc); }
\>\> { return iw8::parser::make_RSHIFT(ctx->loc); }
\|\| { return iw8::parser::make_OR(ctx->loc); }
\&\& { return iw8::parser::make_AND(ctx->loc); }
\=\= { return iw8::parser::make_EQUALITY(ctx->loc); }
\!\= { return iw8::parser::make_INEQUALITY(ctx->loc); }
\<\= { return iw8::parser::make_LESS_EQUAL(ctx->loc); }
\>\= { return iw8::parser::make_GREATER_EQUAL(ctx->loc); }
\< { return iw8::parser::make_LESS(ctx->loc); }
\> { return iw8::parser::make_GREATER(ctx->loc); }
\+\= { return iw8::parser::make_ASSIGN_ADD(ctx->loc); }
\-\= { return iw8::parser::make_ASSIGN_SUB(ctx->loc); }
\*\= { return iw8::parser::make_ASSIGN_MUL(ctx->loc); }
\/\= { return iw8::parser::make_ASSIGN_DIV(ctx->loc); }
\%\= { return iw8::parser::make_ASSIGN_MOD(ctx->loc); }
\|\= { return iw8::parser::make_ASSIGN_BW_OR(ctx->loc); }
\&\= { return iw8::parser::make_ASSIGN_BW_AND(ctx->loc); }
\^\= { return iw8::parser::make_ASSIGN_BW_EXOR(ctx->loc); }
\= { return iw8::parser::make_ASSIGN(ctx->loc); }
\+ { return iw8::parser::make_ADD(ctx->loc); }
\- { return iw8::parser::make_SUB(ctx->loc); }
\* { return iw8::parser::make_MUL(ctx->loc); }
\/ { return iw8::parser::make_DIV(ctx->loc); }
\% { return iw8::parser::make_MOD(ctx->loc); }
\! { return iw8::parser::make_NOT(ctx->loc); }
\~ { return iw8::parser::make_COMPLEMENT(ctx->loc); }
\| { return iw8::parser::make_BITWISE_OR(ctx->loc); }
\& { return iw8::parser::make_BITWISE_AND(ctx->loc); }
\^ { return iw8::parser::make_BITWISE_EXOR(ctx->loc); }
{RGX_PATH} { return iw8::parser::make_PATH(xsk::gsc::iw8::resolver::make_token(std::string_view(yytext, yyleng)), ctx->loc); }
{RGX_IDENTIFIER} { return iw8::parser::make_IDENTIFIER(xsk::gsc::iw8::resolver::make_token(std::string_view(yytext, yyleng)), ctx->loc); }
\&{RGX_STRING} { return iw8::parser::make_ISTRING(std::string(++yytext, --yyleng), ctx->loc); }
{RGX_STRING} { return iw8::parser::make_STRING(std::string(yytext), ctx->loc); }
{RGX_COLOR_S} { return iw8::parser::make_COLOR(std::string(++yytext, --yyleng), ctx->loc); }
{RGX_COLOR_L} { return iw8::parser::make_COLOR(std::string(++yytext, --yyleng), ctx->loc); }
{RGX_FLT_DEC} { return iw8::parser::make_FLOAT(std::string(yytext), ctx->loc); }
{RGX_INT_OCT} { return iw8::parser::make_INTEGER(xsk::utils::string::oct_to_dec(yytext), ctx->loc); }
{RGX_INT_BIN} { return iw8::parser::make_INTEGER(xsk::utils::string::bin_to_dec(yytext), ctx->loc); }
{RGX_INT_HEX} { return iw8::parser::make_INTEGER(xsk::utils::string::hex_to_dec(yytext), ctx->loc); }
{RGX_INT_DEC} { return iw8::parser::make_INTEGER(std::string(yytext), ctx->loc); }
<<EOF>> { if(ctx->header_top > 0) iw8_pop_header(ctx); else return iw8::parser::make_IW8EOF(ctx->loc); }
<*>{RGX_DEFAULT} { throw iw8::parser::syntax_error(ctx->loc, "bad token: \'" + std::string(yytext) + "\'"); }
%%
void iw8_push_header(xsk::gsc::context* ctx, const std::string& file)
{
try
{
if (ctx->header_top >= 4)
{
throw xsk::gsc::error("maximum gsh depth exceeded '4'");
}
ctx->header_top++;
char* buf_data = 0;
size_t buf_size = 0;
for (auto& src : *ctx->sources)
{
if (src.name == file)
{
buf_data = reinterpret_cast<char*>(src.buf.data());
buf_size = src.buf.size();
ctx->locs.push(ctx->loc);
ctx->loc.initialize(&src.name);
}
}
if (buf_data == 0)
{
ctx->sources->push_back(xsk::gsc::source());
auto& source = ctx->sources->back();
source.name = file;
source.buf = ctx->read_callback(file + ".gsh");
source.buf.push_back(0);
source.buf.push_back(0);
buf_data = reinterpret_cast<char*>(source.buf.data());
buf_size = source.buf.size();
ctx->locs.push(ctx->loc);
ctx->loc.initialize(&source.name);
}
auto state = new yy_buffer_state();
state->yy_buf_size = buf_size - 2;
state->yy_buf_pos = state->yy_ch_buf = buf_data;
state->yy_is_our_buffer = 0;
state->yy_input_file = NULL;
state->yy_n_chars = state->yy_buf_size;
state->yy_is_interactive = 0;
state->yy_at_bol = 1;
state->yy_fill_buffer = 0;
state->yy_buffer_status = 0;
yypush_buffer_state(state, ctx->scanner);
}
catch (const std::exception& e)
{
throw xsk::gsc::error("parsing header file '" + file + "': " + e.what());
}
}
void iw8_pop_header(xsk::gsc::context* ctx)
{
ctx->header_top--;
ctx->loc = ctx->locs.top();
ctx->locs.pop();
yypop_buffer_state(ctx->scanner);
}