new lexer and update headers
This commit is contained in:
@ -3,10 +3,7 @@ generate: S4
|
||||
clean:
|
||||
rm -rf ./parser.hpp
|
||||
rm -rf ./parser.cpp
|
||||
rm -rf ./lexer.hpp
|
||||
rm -rf ./lexer.cpp
|
||||
|
||||
S4: lexer.lpp parser.ypp
|
||||
flex lexer.lpp
|
||||
S4: parser.ypp
|
||||
bison parser.ypp -Wcounterexamples
|
||||
mv lexer.hpp lexer.cpp parser.hpp parser.cpp ../../src/s4/xsk/
|
||||
mv parser.hpp parser.cpp ../../src/s4/xsk/
|
||||
|
242
gen/s4/lexer.lpp
242
gen/s4/lexer.lpp
@ -1,242 +0,0 @@
|
||||
/* 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="s4_"
|
||||
%option reentrant
|
||||
%option noyywrap batch nounput noinput
|
||||
%option never-interactive
|
||||
%option nounistd
|
||||
|
||||
%top{
|
||||
#include "stdafx.hpp"
|
||||
#include "s4.hpp"
|
||||
#include "parser.hpp"
|
||||
using namespace xsk::gsc;
|
||||
void s4_push_header(xsk::gsc::context* ctx, const std::string& file);
|
||||
void s4_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 s4::parser::syntax_error(ctx->loc, "unmatched multiline comment start ('/*')"); }
|
||||
<INITIAL>"*/" { throw s4::parser::syntax_error(ctx->loc, "unmatched multiline comment end ('*/')"); }
|
||||
|
||||
<DEV_ON_STATE>"/#" { throw s4::parser::syntax_error(ctx->loc, "cannot recurse devblock ('/#')"); }
|
||||
<DEV_ON_STATE>"#/" { BEGIN(INITIAL); return s4::parser::make_DEVEND(ctx->loc); }
|
||||
<DEV_ON_STATE><<EOF>> { throw s4::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 s4::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 s4::parser::syntax_error(ctx->loc, "unmatched devblock start ('/#')"); }
|
||||
<INITIAL>"#/" { throw s4::parser::syntax_error(ctx->loc, "unmatched devblock end ('#/')"); }
|
||||
|
||||
"#inline" { return s4::parser::make_INLINE(ctx->loc); }
|
||||
"#include" { return s4::parser::make_INCLUDE(ctx->loc); }
|
||||
"#using_animtree" { return s4::parser::make_USINGTREE(ctx->loc); }
|
||||
"#animtree" { return s4::parser::make_ANIMTREE(ctx->loc); }
|
||||
"endon" { return s4::parser::make_ENDON(ctx->loc); }
|
||||
"notify" { return s4::parser::make_NOTIFY(ctx->loc); }
|
||||
"wait" { return s4::parser::make_WAIT(ctx->loc); }
|
||||
"waittill" { return s4::parser::make_WAITTILL(ctx->loc); }
|
||||
"waittillmatch" { return s4::parser::make_WAITTILLMATCH(ctx->loc); }
|
||||
"waittillframeend" { return s4::parser::make_WAITTILLFRAMEEND(ctx->loc); }
|
||||
"waitframe" { return s4::parser::make_WAITFRAME(ctx->loc); }
|
||||
"if" { return s4::parser::make_IF(ctx->loc); }
|
||||
"else" { return s4::parser::make_ELSE(ctx->loc); }
|
||||
"do" { return s4::parser::make_DO(ctx->loc); }
|
||||
"while" { return s4::parser::make_WHILE(ctx->loc); }
|
||||
"for" { return s4::parser::make_FOR(ctx->loc); }
|
||||
"foreach" { return s4::parser::make_FOREACH(ctx->loc); }
|
||||
"in" { return s4::parser::make_IN(ctx->loc); }
|
||||
"switch" { return s4::parser::make_SWITCH(ctx->loc); }
|
||||
"case" { return s4::parser::make_CASE(ctx->loc); }
|
||||
"default" { return s4::parser::make_DEFAULT(ctx->loc); }
|
||||
"break" { return s4::parser::make_BREAK(ctx->loc); }
|
||||
"continue" { return s4::parser::make_CONTINUE(ctx->loc); }
|
||||
"return" { return s4::parser::make_RETURN(ctx->loc); }
|
||||
"breakpoint" { return s4::parser::make_BREAKPOINT(ctx->loc); }
|
||||
"prof_begin" { return s4::parser::make_PROFBEGIN(ctx->loc); }
|
||||
"prof_end" { return s4::parser::make_PROFEND(ctx->loc); }
|
||||
"thread" { return s4::parser::make_THREAD(ctx->loc); }
|
||||
"childthread" { return s4::parser::make_CHILDTHREAD(ctx->loc); }
|
||||
"thisthread" { return s4::parser::make_THISTHREAD(ctx->loc); }
|
||||
"call" { return s4::parser::make_CALL(ctx->loc); }
|
||||
"true" { return s4::parser::make_TRUE(ctx->loc); }
|
||||
"false" { return s4::parser::make_FALSE(ctx->loc); }
|
||||
"undefined" { return s4::parser::make_UNDEFINED(ctx->loc); }
|
||||
".size" { return s4::parser::make_SIZE(ctx->loc); }
|
||||
"game" { return s4::parser::make_GAME(ctx->loc); }
|
||||
"self" { return s4::parser::make_SELF(ctx->loc); }
|
||||
"anim" { return s4::parser::make_ANIM(ctx->loc); }
|
||||
"level" { return s4::parser::make_LEVEL(ctx->loc); }
|
||||
(?i:isdefined) { return s4::parser::make_ISDEFINED(ctx->loc); }
|
||||
(?i:istrue) { return s4::parser::make_ISTRUE(ctx->loc); }
|
||||
\( { return s4::parser::make_LPAREN(ctx->loc); }
|
||||
\) { return s4::parser::make_RPAREN(ctx->loc); }
|
||||
\{ { return s4::parser::make_LBRACE(ctx->loc); }
|
||||
\} { return s4::parser::make_RBRACE(ctx->loc); }
|
||||
\[ { return s4::parser::make_LBRACKET(ctx->loc); }
|
||||
\] { return s4::parser::make_RBRACKET(ctx->loc); }
|
||||
\, { return s4::parser::make_COMMA(ctx->loc); }
|
||||
\. { return s4::parser::make_DOT(ctx->loc); }
|
||||
\:\: { return s4::parser::make_DOUBLECOLON(ctx->loc); }
|
||||
\: { return s4::parser::make_COLON(ctx->loc); }
|
||||
\; { return s4::parser::make_SEMICOLON(ctx->loc); }
|
||||
\? { return s4::parser::make_QMARK(ctx->loc); }
|
||||
\+\+ { return s4::parser::make_INCREMENT(ctx->loc); }
|
||||
\-\- { return s4::parser::make_DECREMENT(ctx->loc); }
|
||||
\<\<\= { return s4::parser::make_ASSIGN_LSHIFT(ctx->loc); }
|
||||
\>\>\= { return s4::parser::make_ASSIGN_RSHIFT(ctx->loc); }
|
||||
\<\< { return s4::parser::make_LSHIFT(ctx->loc); }
|
||||
\>\> { return s4::parser::make_RSHIFT(ctx->loc); }
|
||||
\|\| { return s4::parser::make_OR(ctx->loc); }
|
||||
\&\& { return s4::parser::make_AND(ctx->loc); }
|
||||
\=\= { return s4::parser::make_EQUALITY(ctx->loc); }
|
||||
\!\= { return s4::parser::make_INEQUALITY(ctx->loc); }
|
||||
\<\= { return s4::parser::make_LESS_EQUAL(ctx->loc); }
|
||||
\>\= { return s4::parser::make_GREATER_EQUAL(ctx->loc); }
|
||||
\< { return s4::parser::make_LESS(ctx->loc); }
|
||||
\> { return s4::parser::make_GREATER(ctx->loc); }
|
||||
\+\= { return s4::parser::make_ASSIGN_ADD(ctx->loc); }
|
||||
\-\= { return s4::parser::make_ASSIGN_SUB(ctx->loc); }
|
||||
\*\= { return s4::parser::make_ASSIGN_MUL(ctx->loc); }
|
||||
\/\= { return s4::parser::make_ASSIGN_DIV(ctx->loc); }
|
||||
\%\= { return s4::parser::make_ASSIGN_MOD(ctx->loc); }
|
||||
\|\= { return s4::parser::make_ASSIGN_BW_OR(ctx->loc); }
|
||||
\&\= { return s4::parser::make_ASSIGN_BW_AND(ctx->loc); }
|
||||
\^\= { return s4::parser::make_ASSIGN_BW_EXOR(ctx->loc); }
|
||||
\= { return s4::parser::make_ASSIGN(ctx->loc); }
|
||||
\+ { return s4::parser::make_ADD(ctx->loc); }
|
||||
\- { return s4::parser::make_SUB(ctx->loc); }
|
||||
\* { return s4::parser::make_MUL(ctx->loc); }
|
||||
\/ { return s4::parser::make_DIV(ctx->loc); }
|
||||
\% { return s4::parser::make_MOD(ctx->loc); }
|
||||
\! { return s4::parser::make_NOT(ctx->loc); }
|
||||
\~ { return s4::parser::make_COMPLEMENT(ctx->loc); }
|
||||
\| { return s4::parser::make_BITWISE_OR(ctx->loc); }
|
||||
\& { return s4::parser::make_BITWISE_AND(ctx->loc); }
|
||||
\^ { return s4::parser::make_BITWISE_EXOR(ctx->loc); }
|
||||
{RGX_PATH} { return s4::parser::make_PATH(xsk::gsc::s4::resolver::make_token(std::string_view(yytext, yyleng)), ctx->loc); }
|
||||
{RGX_IDENTIFIER} { return s4::parser::make_IDENTIFIER(xsk::gsc::s4::resolver::make_token(std::string_view(yytext, yyleng)), ctx->loc); }
|
||||
\&{RGX_STRING} { return s4::parser::make_ISTRING(std::string(++yytext, --yyleng), ctx->loc); }
|
||||
{RGX_STRING} { return s4::parser::make_STRING(std::string(yytext), ctx->loc); }
|
||||
{RGX_COLOR_S} { return s4::parser::make_COLOR(std::string(++yytext, --yyleng), ctx->loc); }
|
||||
{RGX_COLOR_L} { return s4::parser::make_COLOR(std::string(++yytext, --yyleng), ctx->loc); }
|
||||
{RGX_FLT_DEC} { return s4::parser::make_FLOAT(std::string(yytext), ctx->loc); }
|
||||
{RGX_INT_OCT} { return s4::parser::make_INTEGER(xsk::utils::string::oct_to_dec(yytext), ctx->loc); }
|
||||
{RGX_INT_BIN} { return s4::parser::make_INTEGER(xsk::utils::string::bin_to_dec(yytext), ctx->loc); }
|
||||
{RGX_INT_HEX} { return s4::parser::make_INTEGER(xsk::utils::string::hex_to_dec(yytext), ctx->loc); }
|
||||
{RGX_INT_DEC} { return s4::parser::make_INTEGER(std::string(yytext), ctx->loc); }
|
||||
<<EOF>> { if(ctx->header_top > 0) s4_pop_header(ctx); else return s4::parser::make_S4EOF(ctx->loc); }
|
||||
<*>{RGX_DEFAULT} { throw s4::parser::syntax_error(ctx->loc, "bad token: \'" + std::string(yytext) + "\'"); }
|
||||
|
||||
%%
|
||||
|
||||
void s4_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 s4_pop_header(xsk::gsc::context* ctx)
|
||||
{
|
||||
ctx->header_top--;
|
||||
ctx->loc = ctx->locs.top();
|
||||
ctx->locs.pop();
|
||||
yypop_buffer_state(ctx->scanner);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2021 xensik. All rights reserved.
|
||||
/* Copyright 2022 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
@ -19,21 +19,15 @@
|
||||
%define parse.trace
|
||||
%define parse.error detailed
|
||||
%define parse.lac full
|
||||
|
||||
%locations
|
||||
|
||||
%lex-param { yyscan_t yyscanner }
|
||||
%lex-param { xsk::gsc::context* ctx }
|
||||
|
||||
%parse-param { yyscan_t yyscanner }
|
||||
%parse-param { xsk::gsc::context* ctx }
|
||||
%lex-param { xsk::gsc::s4::lexer& lexer }
|
||||
%parse-param { xsk::gsc::s4::lexer& lexer }
|
||||
%parse-param { xsk::gsc::ast::program::ptr& ast }
|
||||
|
||||
%code requires
|
||||
{
|
||||
#include "s4.hpp"
|
||||
typedef void *yyscan_t;
|
||||
#define YY_DECL xsk::gsc::s4::parser::symbol_type S4lex(yyscan_t yyscanner, xsk::gsc::context* ctx)
|
||||
namespace xsk::gsc::s4 { class lexer; }
|
||||
}
|
||||
|
||||
%code top
|
||||
@ -42,7 +36,7 @@ typedef void *yyscan_t;
|
||||
#include "parser.hpp"
|
||||
#include "lexer.hpp"
|
||||
using namespace xsk::gsc;
|
||||
xsk::gsc::s4::parser::symbol_type S4lex(yyscan_t yyscanner, xsk::gsc::context* ctx);
|
||||
xsk::gsc::s4::parser::symbol_type S4lex(xsk::gsc::s4::lexer& lexer);
|
||||
}
|
||||
|
||||
%token DEVBEGIN "/#"
|
||||
@ -272,7 +266,7 @@ program
|
||||
;
|
||||
|
||||
inline
|
||||
: INLINE expr_path SEMICOLON { s4_push_header(ctx, $2->value); }
|
||||
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
|
||||
;
|
||||
|
||||
include
|
||||
@ -290,7 +284,7 @@ declaration
|
||||
|
||||
decl_usingtree
|
||||
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
|
||||
{ ctx->restrict_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
|
||||
{ lexer.restrict_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
|
||||
;
|
||||
|
||||
decl_constant
|
||||
@ -300,7 +294,7 @@ decl_constant
|
||||
|
||||
decl_thread
|
||||
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
|
||||
{ ctx->restrict_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
|
||||
{ lexer.restrict_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
|
||||
;
|
||||
|
||||
stmt
|
||||
|
Reference in New Issue
Block a user