Replace object parser with lalr library
This commit is contained in:
parent
3ba4bef93b
commit
f666416696
13 changed files with 499 additions and 995 deletions
|
|
@ -1,13 +1,17 @@
|
||||||
project(Objects)
|
project(Objects)
|
||||||
|
|
||||||
|
### ---------------------- Externals --------------------- ###
|
||||||
|
set(BINDINGS_INCLUDE ../Externals/lalr/src)
|
||||||
|
# set(BINDINGS_LIBS )
|
||||||
|
|
||||||
### ---------------------- Static Library --------------------- ###
|
### ---------------------- Static Library --------------------- ###
|
||||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
||||||
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp" "./applications/*.hpp")
|
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp" "./applications/*.hpp")
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ${BINDINGS_INCLUDE})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Strings Math Tokenizer CommandLine Connection)
|
target_link_libraries(${PROJECT_NAME} PUBLIC Strings Math Connection)
|
||||||
|
|
||||||
### -------------------------- Applications -------------------------- ###
|
### -------------------------- Applications -------------------------- ###
|
||||||
#add_executable(osc ./applications/Compiler.cpp)
|
#add_executable(osc ./applications/Compiler.cpp)
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,9 @@ void FunctionDefinition::EvalStatement(Statement* stm) {
|
||||||
// compile function
|
// compile function
|
||||||
for (auto child_stm : stm_class_def->mScope->mStatements) {
|
for (auto child_stm : stm_class_def->mScope->mStatements) {
|
||||||
// check for return statements
|
// check for return statements
|
||||||
ASSERT(child_stm.data()->mType != Statement::Type::RET && "return statements are not allowed in class definition");
|
ASSERT(
|
||||||
|
child_stm.data()->mType != Statement::Type::RET && "return statements are not allowed in class definition"
|
||||||
|
);
|
||||||
func.EvalStatement(child_stm.data());
|
func.EvalStatement(child_stm.data());
|
||||||
}
|
}
|
||||||
// create one last instruction - constructing class from function execution state
|
// create one last instruction - constructing class from function execution state
|
||||||
|
|
@ -580,8 +582,8 @@ bool obj::BCgen::Compile(obj::MethodObject* method) {
|
||||||
|
|
||||||
if (res.err) {
|
if (res.err) {
|
||||||
// TODO : print parse error
|
// TODO : print parse error
|
||||||
auto loc = res.err->get_err_location(script.read());
|
auto loc = res.err->getErrorLocation(script.read());
|
||||||
printf("Parser Error (%i,%i): %s\n", loc.head, loc.tail, res.err->mDescr.read());
|
printf("Parser Error (%i,%i): %s\n", loc.head, loc.tail, res.err->mDescription.read());
|
||||||
// tp::gLogeer->write(tp::sfmt("Parser Error (%i,%i): \n", loc.head, loc.tail), true, tp::Logger::LogEntry::ERR);
|
// tp::gLogeer->write(tp::sfmt("Parser Error (%i,%i): \n", loc.head, loc.tail), true, tp::Logger::LogEntry::ERR);
|
||||||
// tp::GLog->write(res.err->mDescr, true, tp::Logger::LogEntry::ERR);
|
// tp::GLog->write(res.err->mDescr, true, tp::Logger::LogEntry::ERR);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
|
|
||||||
#include "Tokenizer.hpp"
|
|
||||||
|
|
||||||
#include "compiler/function.h"
|
#include "compiler/function.h"
|
||||||
|
|
||||||
#include "primitives/boolobject.h"
|
#include "primitives/boolobject.h"
|
||||||
|
|
@ -81,9 +79,8 @@ static tp::ModuleManifest* sModuleDependencies[] = {
|
||||||
// &tp::gModuleCompressor,
|
// &tp::gModuleCompressor,
|
||||||
&tp::gModuleMath,
|
&tp::gModuleMath,
|
||||||
&tp::gModuleStrings,
|
&tp::gModuleStrings,
|
||||||
&tp::gModuleTokenizer,
|
|
||||||
&tp::gModuleConnection,
|
&tp::gModuleConnection,
|
||||||
NULL
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
tp::ModuleManifest obj::gModuleObjects = tp::ModuleManifest("Objects", init, deinit, sModuleDependencies);
|
tp::ModuleManifest obj::gModuleObjects = tp::ModuleManifest("Objects", init, deinit, sModuleDependencies);
|
||||||
|
|
|
||||||
332
Objects/private/parser/oscript.cpp
Normal file
332
Objects/private/parser/oscript.cpp
Normal file
|
|
@ -0,0 +1,332 @@
|
||||||
|
|
||||||
|
#include <lalr/ParserStateMachine.hpp>
|
||||||
|
#include <lalr/ParserState.hpp>
|
||||||
|
#include <lalr/ParserTransition.hpp>
|
||||||
|
#include <lalr/ParserSymbol.hpp>
|
||||||
|
#include <lalr/ParserAction.hpp>
|
||||||
|
#include <lalr/LexerStateMachine.hpp>
|
||||||
|
#include <lalr/LexerState.hpp>
|
||||||
|
#include <lalr/LexerTransition.hpp>
|
||||||
|
#include <lalr/LexerAction.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
using namespace lalr;
|
||||||
|
|
||||||
|
extern const LexerAction lexer_actions [];
|
||||||
|
extern const LexerTransition lexer_transitions [];
|
||||||
|
extern const LexerState lexer_states [];
|
||||||
|
extern const LexerAction whitespace_lexer_actions [];
|
||||||
|
extern const LexerTransition whitespace_lexer_transitions [];
|
||||||
|
extern const LexerState whitespace_lexer_states [];
|
||||||
|
extern const ParserAction actions [];
|
||||||
|
extern const ParserSymbol symbols [];
|
||||||
|
extern const ParserTransition transitions [];
|
||||||
|
extern const ParserState states [];
|
||||||
|
|
||||||
|
const ParserAction actions [] =
|
||||||
|
{
|
||||||
|
{0, "scope"},
|
||||||
|
{1, "stm_scope_append"},
|
||||||
|
{2, "stm_scope_create"},
|
||||||
|
{3, "tmp"},
|
||||||
|
{4, "stm_defVar"},
|
||||||
|
{5, "stm_log"},
|
||||||
|
{6, "expr_bool"},
|
||||||
|
{7, "expr_int"},
|
||||||
|
{8, "expr_float"},
|
||||||
|
{9, "expr_string"},
|
||||||
|
{-1, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ParserSymbol symbols [] =
|
||||||
|
{
|
||||||
|
{0, (SymbolType) 2, "dot_start", ".start", "dot_start"},
|
||||||
|
{1, (SymbolType) 3, "dot_end", ".end", "dot_end"},
|
||||||
|
{2, (SymbolType) 1, "error", "error", "error"},
|
||||||
|
{3, (SymbolType) 1, "dot_whitespace", ".whitespace", "dot_whitespace"},
|
||||||
|
{4, (SymbolType) 2, "scope", "scope", "scope"},
|
||||||
|
{5, (SymbolType) 1, "left_curly_brace_terminal", "{", "{"},
|
||||||
|
{6, (SymbolType) 2, "statements", "statements", "statements"},
|
||||||
|
{7, (SymbolType) 1, "right_curly_brace_terminal", "}", "}"},
|
||||||
|
{8, (SymbolType) 1, "semi_colon_terminal", ";", ";"},
|
||||||
|
{9, (SymbolType) 2, "statement", "statement", "statement"},
|
||||||
|
{10, (SymbolType) 2, "statementVar", "statementVar", "statementVar"},
|
||||||
|
{11, (SymbolType) 2, "statementLog", "statementLog", "statementLog"},
|
||||||
|
{12, (SymbolType) 1, "var_terminal", "var", "var"},
|
||||||
|
{13, (SymbolType) 1, "print_terminal", "print", "print"},
|
||||||
|
{14, (SymbolType) 2, "value", "value", "value"},
|
||||||
|
{15, (SymbolType) 1, "id", "[a-z]", "id"},
|
||||||
|
{16, (SymbolType) 1, "boolean", "true|false", "boolean"},
|
||||||
|
{17, (SymbolType) 1, "integer", "(\\+|\\-)?[0-9]+", "integer"},
|
||||||
|
{18, (SymbolType) 1, "real", "(\\+|\\-)?[0-9]+(\\.[0-9]+)?((e|E)(\\+|\\-)?[0-9]+)?", "real"},
|
||||||
|
{19, (SymbolType) 1, "string", "[\\\"']:string:", "string"},
|
||||||
|
{-1, (SymbolType) 0, nullptr, nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ParserTransition transitions [] =
|
||||||
|
{
|
||||||
|
{&symbols[4], &states[1], nullptr, 0, 0, 0, 0},
|
||||||
|
{&symbols[5], &states[2], nullptr, 0, 0, 0, 1},
|
||||||
|
{&symbols[1], nullptr, &symbols[4], 0, 0, -1, 2},
|
||||||
|
{&symbols[1], nullptr, &symbols[0], 1, 0, -1, 3},
|
||||||
|
{&symbols[6], &states[3], nullptr, 0, 0, 0, 4},
|
||||||
|
{&symbols[9], &states[8], nullptr, 0, 0, 0, 5},
|
||||||
|
{&symbols[10], &states[9], nullptr, 0, 0, 0, 6},
|
||||||
|
{&symbols[11], &states[10], nullptr, 0, 0, 0, 7},
|
||||||
|
{&symbols[12], &states[11], nullptr, 0, 0, 0, 8},
|
||||||
|
{&symbols[13], &states[13], nullptr, 0, 0, 0, 9},
|
||||||
|
{&symbols[7], nullptr, &symbols[6], 0, 0, -1, 10},
|
||||||
|
{&symbols[8], nullptr, &symbols[6], 0, 0, -1, 11},
|
||||||
|
{&symbols[7], &states[4], nullptr, 0, 0, 0, 12},
|
||||||
|
{&symbols[8], &states[5], nullptr, 0, 0, 0, 13},
|
||||||
|
{&symbols[1], nullptr, &symbols[4], 3, 0, 0, 14},
|
||||||
|
{&symbols[9], &states[6], nullptr, 0, 0, 0, 15},
|
||||||
|
{&symbols[10], &states[9], nullptr, 0, 0, 0, 16},
|
||||||
|
{&symbols[11], &states[10], nullptr, 0, 0, 0, 17},
|
||||||
|
{&symbols[12], &states[11], nullptr, 0, 0, 0, 18},
|
||||||
|
{&symbols[13], &states[13], nullptr, 0, 0, 0, 19},
|
||||||
|
{&symbols[8], &states[7], nullptr, 0, 0, 0, 20},
|
||||||
|
{&symbols[7], nullptr, &symbols[6], 4, 0, 1, 21},
|
||||||
|
{&symbols[8], nullptr, &symbols[6], 4, 0, 1, 22},
|
||||||
|
{&symbols[7], nullptr, &symbols[6], 1, 0, 2, 23},
|
||||||
|
{&symbols[8], nullptr, &symbols[6], 1, 0, 2, 24},
|
||||||
|
{&symbols[7], nullptr, &symbols[9], 1, 0, 3, 25},
|
||||||
|
{&symbols[8], nullptr, &symbols[9], 1, 0, 3, 26},
|
||||||
|
{&symbols[7], nullptr, &symbols[9], 1, 0, 3, 27},
|
||||||
|
{&symbols[8], nullptr, &symbols[9], 1, 0, 3, 28},
|
||||||
|
{&symbols[15], &states[12], nullptr, 0, 0, 0, 29},
|
||||||
|
{&symbols[7], nullptr, &symbols[10], 2, 0, 4, 30},
|
||||||
|
{&symbols[8], nullptr, &symbols[10], 2, 0, 4, 31},
|
||||||
|
{&symbols[14], &states[14], nullptr, 0, 0, 0, 32},
|
||||||
|
{&symbols[16], &states[15], nullptr, 0, 0, 0, 33},
|
||||||
|
{&symbols[17], &states[16], nullptr, 0, 0, 0, 34},
|
||||||
|
{&symbols[18], &states[17], nullptr, 0, 0, 0, 35},
|
||||||
|
{&symbols[19], &states[18], nullptr, 0, 0, 0, 36},
|
||||||
|
{&symbols[7], nullptr, &symbols[14], 0, 0, -1, 37},
|
||||||
|
{&symbols[8], nullptr, &symbols[14], 0, 0, -1, 38},
|
||||||
|
{&symbols[7], nullptr, &symbols[11], 2, 0, 5, 39},
|
||||||
|
{&symbols[8], nullptr, &symbols[11], 2, 0, 5, 40},
|
||||||
|
{&symbols[7], nullptr, &symbols[14], 1, 0, 6, 41},
|
||||||
|
{&symbols[8], nullptr, &symbols[14], 1, 0, 6, 42},
|
||||||
|
{&symbols[7], nullptr, &symbols[14], 1, 0, 7, 43},
|
||||||
|
{&symbols[8], nullptr, &symbols[14], 1, 0, 7, 44},
|
||||||
|
{&symbols[7], nullptr, &symbols[14], 1, 0, 8, 45},
|
||||||
|
{&symbols[8], nullptr, &symbols[14], 1, 0, 8, 46},
|
||||||
|
{&symbols[7], nullptr, &symbols[14], 1, 0, 9, 47},
|
||||||
|
{&symbols[8], nullptr, &symbols[14], 1, 0, 9, 48},
|
||||||
|
{nullptr, nullptr, nullptr, 0, 0, 0, -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ParserState states [] =
|
||||||
|
{
|
||||||
|
{0, 3, &transitions[0], "(null)"},
|
||||||
|
{1, 1, &transitions[3], "(null)"},
|
||||||
|
{2, 8, &transitions[4], "(null)"},
|
||||||
|
{3, 2, &transitions[12], "(null)"},
|
||||||
|
{4, 1, &transitions[14], "(null)"},
|
||||||
|
{5, 5, &transitions[15], "(null)"},
|
||||||
|
{6, 1, &transitions[20], "(null)"},
|
||||||
|
{7, 2, &transitions[21], "(null)"},
|
||||||
|
{8, 2, &transitions[23], "(null)"},
|
||||||
|
{9, 2, &transitions[25], "(null)"},
|
||||||
|
{10, 2, &transitions[27], "(null)"},
|
||||||
|
{11, 1, &transitions[29], "(null)"},
|
||||||
|
{12, 2, &transitions[30], "(null)"},
|
||||||
|
{13, 7, &transitions[32], "(null)"},
|
||||||
|
{14, 2, &transitions[39], "(null)"},
|
||||||
|
{15, 2, &transitions[41], "(null)"},
|
||||||
|
{16, 2, &transitions[43], "(null)"},
|
||||||
|
{17, 2, &transitions[45], "(null)"},
|
||||||
|
{18, 2, &transitions[47], "(null)"},
|
||||||
|
{-1, 0, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerAction lexer_actions [] =
|
||||||
|
{
|
||||||
|
{0, "string"},
|
||||||
|
{-1, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerTransition lexer_transitions [] =
|
||||||
|
{
|
||||||
|
{34, 35, &lexer_states[45], nullptr},
|
||||||
|
{39, 40, &lexer_states[45], nullptr},
|
||||||
|
{43, 44, &lexer_states[38], nullptr},
|
||||||
|
{45, 46, &lexer_states[38], nullptr},
|
||||||
|
{46, 47, &lexer_states[6], nullptr},
|
||||||
|
{48, 58, &lexer_states[37], nullptr},
|
||||||
|
{59, 60, &lexer_states[19], nullptr},
|
||||||
|
{97, 101, &lexer_states[28], nullptr},
|
||||||
|
{101, 102, &lexer_states[1], nullptr},
|
||||||
|
{102, 103, &lexer_states[30], nullptr},
|
||||||
|
{103, 112, &lexer_states[28], nullptr},
|
||||||
|
{112, 113, &lexer_states[23], nullptr},
|
||||||
|
{113, 116, &lexer_states[28], nullptr},
|
||||||
|
{116, 117, &lexer_states[29], nullptr},
|
||||||
|
{117, 118, &lexer_states[28], nullptr},
|
||||||
|
{118, 119, &lexer_states[20], nullptr},
|
||||||
|
{119, 123, &lexer_states[28], nullptr},
|
||||||
|
{123, 124, &lexer_states[17], nullptr},
|
||||||
|
{125, 126, &lexer_states[18], nullptr},
|
||||||
|
{114, 115, &lexer_states[2], nullptr},
|
||||||
|
{114, 115, &lexer_states[3], nullptr},
|
||||||
|
{111, 112, &lexer_states[4], nullptr},
|
||||||
|
{114, 115, &lexer_states[5], nullptr},
|
||||||
|
{119, 120, &lexer_states[7], nullptr},
|
||||||
|
{104, 105, &lexer_states[8], nullptr},
|
||||||
|
{105, 106, &lexer_states[9], nullptr},
|
||||||
|
{116, 117, &lexer_states[10], nullptr},
|
||||||
|
{101, 102, &lexer_states[11], nullptr},
|
||||||
|
{115, 116, &lexer_states[12], nullptr},
|
||||||
|
{112, 113, &lexer_states[13], nullptr},
|
||||||
|
{97, 98, &lexer_states[14], nullptr},
|
||||||
|
{99, 100, &lexer_states[15], nullptr},
|
||||||
|
{101, 102, &lexer_states[16], nullptr},
|
||||||
|
{97, 98, &lexer_states[21], nullptr},
|
||||||
|
{114, 115, &lexer_states[22], nullptr},
|
||||||
|
{114, 115, &lexer_states[24], nullptr},
|
||||||
|
{105, 106, &lexer_states[25], nullptr},
|
||||||
|
{110, 111, &lexer_states[26], nullptr},
|
||||||
|
{116, 117, &lexer_states[27], nullptr},
|
||||||
|
{114, 115, &lexer_states[31], nullptr},
|
||||||
|
{97, 98, &lexer_states[33], nullptr},
|
||||||
|
{117, 118, &lexer_states[32], nullptr},
|
||||||
|
{101, 102, &lexer_states[36], nullptr},
|
||||||
|
{108, 109, &lexer_states[34], nullptr},
|
||||||
|
{115, 116, &lexer_states[35], nullptr},
|
||||||
|
{101, 102, &lexer_states[36], nullptr},
|
||||||
|
{46, 47, &lexer_states[39], nullptr},
|
||||||
|
{48, 58, &lexer_states[37], nullptr},
|
||||||
|
{69, 70, &lexer_states[41], nullptr},
|
||||||
|
{101, 102, &lexer_states[41], nullptr},
|
||||||
|
{48, 58, &lexer_states[37], nullptr},
|
||||||
|
{48, 58, &lexer_states[40], nullptr},
|
||||||
|
{48, 58, &lexer_states[40], nullptr},
|
||||||
|
{69, 70, &lexer_states[41], nullptr},
|
||||||
|
{101, 102, &lexer_states[41], nullptr},
|
||||||
|
{43, 44, &lexer_states[42], nullptr},
|
||||||
|
{45, 46, &lexer_states[42], nullptr},
|
||||||
|
{48, 58, &lexer_states[43], nullptr},
|
||||||
|
{48, 58, &lexer_states[43], nullptr},
|
||||||
|
{48, 58, &lexer_states[43], nullptr},
|
||||||
|
{0, 2147483647, &lexer_states[44], &lexer_actions[0]},
|
||||||
|
{-1, -1, nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerState lexer_states [] =
|
||||||
|
{
|
||||||
|
{0, 19, &lexer_transitions[0], nullptr},
|
||||||
|
{1, 1, &lexer_transitions[19], &symbols[15]},
|
||||||
|
{2, 1, &lexer_transitions[20], nullptr},
|
||||||
|
{3, 1, &lexer_transitions[21], nullptr},
|
||||||
|
{4, 1, &lexer_transitions[22], nullptr},
|
||||||
|
{5, 0, &lexer_transitions[23], &symbols[2]},
|
||||||
|
{6, 1, &lexer_transitions[23], nullptr},
|
||||||
|
{7, 1, &lexer_transitions[24], nullptr},
|
||||||
|
{8, 1, &lexer_transitions[25], nullptr},
|
||||||
|
{9, 1, &lexer_transitions[26], nullptr},
|
||||||
|
{10, 1, &lexer_transitions[27], nullptr},
|
||||||
|
{11, 1, &lexer_transitions[28], nullptr},
|
||||||
|
{12, 1, &lexer_transitions[29], nullptr},
|
||||||
|
{13, 1, &lexer_transitions[30], nullptr},
|
||||||
|
{14, 1, &lexer_transitions[31], nullptr},
|
||||||
|
{15, 1, &lexer_transitions[32], nullptr},
|
||||||
|
{16, 0, &lexer_transitions[33], &symbols[3]},
|
||||||
|
{17, 0, &lexer_transitions[33], &symbols[5]},
|
||||||
|
{18, 0, &lexer_transitions[33], &symbols[7]},
|
||||||
|
{19, 0, &lexer_transitions[33], &symbols[8]},
|
||||||
|
{20, 1, &lexer_transitions[33], &symbols[15]},
|
||||||
|
{21, 1, &lexer_transitions[34], nullptr},
|
||||||
|
{22, 0, &lexer_transitions[35], &symbols[12]},
|
||||||
|
{23, 1, &lexer_transitions[35], &symbols[15]},
|
||||||
|
{24, 1, &lexer_transitions[36], nullptr},
|
||||||
|
{25, 1, &lexer_transitions[37], nullptr},
|
||||||
|
{26, 1, &lexer_transitions[38], nullptr},
|
||||||
|
{27, 0, &lexer_transitions[39], &symbols[13]},
|
||||||
|
{28, 0, &lexer_transitions[39], &symbols[15]},
|
||||||
|
{29, 1, &lexer_transitions[39], &symbols[15]},
|
||||||
|
{30, 1, &lexer_transitions[40], &symbols[15]},
|
||||||
|
{31, 1, &lexer_transitions[41], nullptr},
|
||||||
|
{32, 1, &lexer_transitions[42], nullptr},
|
||||||
|
{33, 1, &lexer_transitions[43], nullptr},
|
||||||
|
{34, 1, &lexer_transitions[44], nullptr},
|
||||||
|
{35, 1, &lexer_transitions[45], nullptr},
|
||||||
|
{36, 0, &lexer_transitions[46], &symbols[16]},
|
||||||
|
{37, 4, &lexer_transitions[46], &symbols[17]},
|
||||||
|
{38, 1, &lexer_transitions[50], nullptr},
|
||||||
|
{39, 1, &lexer_transitions[51], nullptr},
|
||||||
|
{40, 3, &lexer_transitions[52], &symbols[18]},
|
||||||
|
{41, 3, &lexer_transitions[55], nullptr},
|
||||||
|
{42, 1, &lexer_transitions[58], nullptr},
|
||||||
|
{43, 1, &lexer_transitions[59], &symbols[18]},
|
||||||
|
{44, 0, &lexer_transitions[60], &symbols[19]},
|
||||||
|
{45, 1, &lexer_transitions[60], nullptr},
|
||||||
|
{-1, 0, nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerStateMachine lexer_state_machine =
|
||||||
|
{
|
||||||
|
1, // #actions
|
||||||
|
61, // #transitions
|
||||||
|
46, // #states
|
||||||
|
lexer_actions, // actions
|
||||||
|
lexer_transitions, // transitions
|
||||||
|
lexer_states, // states
|
||||||
|
&lexer_states[0] // start state
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerAction whitespace_lexer_actions [] =
|
||||||
|
{
|
||||||
|
{-1, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerTransition whitespace_lexer_transitions [] =
|
||||||
|
{
|
||||||
|
{9, 11, &whitespace_lexer_states[0], nullptr},
|
||||||
|
{13, 14, &whitespace_lexer_states[0], nullptr},
|
||||||
|
{32, 33, &whitespace_lexer_states[0], nullptr},
|
||||||
|
{-1, -1, nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerState whitespace_lexer_states [] =
|
||||||
|
{
|
||||||
|
{0, 3, &whitespace_lexer_transitions[0], &symbols[3]},
|
||||||
|
{-1, 0, nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LexerStateMachine whitespace_lexer_state_machine =
|
||||||
|
{
|
||||||
|
0, // #actions
|
||||||
|
3, // #transitions
|
||||||
|
1, // #states
|
||||||
|
whitespace_lexer_actions, // actions
|
||||||
|
whitespace_lexer_transitions, // transitions
|
||||||
|
whitespace_lexer_states, // states
|
||||||
|
&whitespace_lexer_states[0] // start state
|
||||||
|
};
|
||||||
|
|
||||||
|
const ParserStateMachine parser_state_machine =
|
||||||
|
{
|
||||||
|
"oscript",
|
||||||
|
10, // #actions
|
||||||
|
20, // #symbols
|
||||||
|
49, // #transitions
|
||||||
|
19, // #states
|
||||||
|
actions,
|
||||||
|
symbols,
|
||||||
|
transitions,
|
||||||
|
states,
|
||||||
|
&symbols[0], // start symbol
|
||||||
|
&symbols[1], // end symbol
|
||||||
|
&symbols[2], // error symbol
|
||||||
|
&symbols[3], // whitespace symbol
|
||||||
|
&states[0], // start state
|
||||||
|
&lexer_state_machine, // lexer state machine
|
||||||
|
&whitespace_lexer_state_machine // whitespace lexer state machine
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const lalr::ParserStateMachine* oscript_parser_state_machine = &parser_state_machine;
|
||||||
33
Objects/private/parser/oscript.g
Normal file
33
Objects/private/parser/oscript.g
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
oscript {
|
||||||
|
%whitespace "[ \t\r\n]*";
|
||||||
|
|
||||||
|
scope:
|
||||||
|
'{' statements '}' [scope]
|
||||||
|
| ;
|
||||||
|
|
||||||
|
statements:
|
||||||
|
statements ';' statement ';' [stm_scope_append]
|
||||||
|
| statement [stm_scope_create]
|
||||||
|
| ;
|
||||||
|
|
||||||
|
statement:
|
||||||
|
statementVar [tmp]
|
||||||
|
| statementLog [tmp];
|
||||||
|
|
||||||
|
statementVar: 'var' id [stm_defVar];
|
||||||
|
statementLog: 'print' value [stm_log];
|
||||||
|
|
||||||
|
value:
|
||||||
|
boolean [expr_bool]
|
||||||
|
| integer [expr_int]
|
||||||
|
| real [expr_float]
|
||||||
|
| string [expr_string]
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
id: "[a-z]";
|
||||||
|
boolean: "true|false";
|
||||||
|
integer: "(\+|\-)?[0-9]+";
|
||||||
|
real: "(\+|\-)?[0-9]+(\.[0-9]+)?((e|E)(\+|\-)?[0-9]+)?";
|
||||||
|
string: "[\"']:string:";
|
||||||
|
}
|
||||||
|
|
@ -1,840 +1,105 @@
|
||||||
|
|
||||||
#include "List.hpp"
|
|
||||||
#include "Logging.hpp"
|
|
||||||
|
|
||||||
#include "compiler/function.h"
|
#include <parser/parser.h>
|
||||||
#include "parser/parser.h"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
// #include "compiler/function.h"
|
||||||
|
|
||||||
#define MAX_STREAM_LENGTH 1024 * 8 * 200
|
#include <lalr/Parser.hpp>
|
||||||
|
#include <lalr/string_literal.hpp>
|
||||||
|
|
||||||
#define REQUIRE(expr, desc, on_catch) \
|
|
||||||
DEBUG_BREAK(mRes.err); \
|
|
||||||
if (!(expr)) { \
|
|
||||||
mRes.err = new Error(desc, mTok.getCursorPrev().mAdvancedOffset); \
|
|
||||||
on_catch; \
|
|
||||||
return NULL; \
|
|
||||||
}
|
|
||||||
#define CHECK(expr, on_catch) \
|
|
||||||
if (!(expr)) { \
|
|
||||||
on_catch; \
|
|
||||||
return NULL; \
|
|
||||||
}
|
|
||||||
#define CHECK_ERROR(value, on_catch) \
|
|
||||||
if (mRes.err || !value) { \
|
|
||||||
on_catch; \
|
|
||||||
return NULL; \
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace tp;
|
|
||||||
using namespace obj;
|
using namespace obj;
|
||||||
using namespace BCgen;
|
|
||||||
|
|
||||||
bool Parser::Token::isAriphm() {
|
struct ASTNode {
|
||||||
switch (type) {
|
BCgen::Expression* expression = nullptr;
|
||||||
case Token::ADD:
|
BCgen::Statement* statement = nullptr;
|
||||||
case Token::SUB:
|
};
|
||||||
case Token::DIV:
|
|
||||||
case Token::MUL: return true;
|
extern const lalr::ParserStateMachine* oscript_parser_state_machine;
|
||||||
default: return false;
|
typedef void* UserData;
|
||||||
|
typedef char SymbolType;
|
||||||
|
|
||||||
|
typedef std::basic_string<SymbolType>::iterator IteratorType;
|
||||||
|
|
||||||
|
namespace action {
|
||||||
|
static UserData expr_bool(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
return new BCgen::ExpressionConst(nodes[0].lexeme() == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData expr_int(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData expr_float(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData expr_string(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData stm_log(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
auto expr = (BCgen::Expression*) (start[1]);
|
||||||
|
return new BCgen::StatementPrint(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData stm_defVar(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
return new BCgen::StatementLocalDef(nodes[1].lexeme().c_str(), new BCgen::ExpressionConst(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData stm_scope_append(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
auto scope = (BCgen::StatementScope*) start[0];
|
||||||
|
auto stm = (BCgen::Statement*) start[2];
|
||||||
|
scope->mStatements.append(stm);
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData stm_scope_create(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
auto stm = (BCgen::Statement*) start[0];
|
||||||
|
return new BCgen::StatementScope({ stm }, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData scope(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
return start[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserData tmp(const UserData* start, const lalr::ParserNode<SymbolType>* nodes, size_t length) {
|
||||||
|
return *start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::Token::isBoolean() {
|
Parser::Result Parser::parse(const tp::String& stream) {
|
||||||
switch (type) {
|
|
||||||
case Token::EQUAL:
|
lalr::ErrorPolicy errorPolicy;
|
||||||
case Token::NOT_EQUAL:
|
|
||||||
case Token::BOOL_AND:
|
lalr::Parser<IteratorType, UserData> parser(oscript_parser_state_machine, &errorPolicy);
|
||||||
case Token::BOOL_OR:
|
|
||||||
case Token::MORE:
|
parser.set_lexer_action_handler("string", &lalr::string_literal<IteratorType>);
|
||||||
case Token::LESS:
|
|
||||||
case Token::QE_OR_MORE:
|
parser.set_action_handler("expr_bool", &action::expr_bool);
|
||||||
case Token::QE_OR_LESS: return true;
|
parser.set_action_handler("expr_int", &action::expr_int);
|
||||||
default: return false;
|
parser.set_action_handler("expr_float", &action::expr_float);
|
||||||
}
|
parser.set_action_handler("expr_string", &action::expr_string);
|
||||||
}
|
|
||||||
|
parser.set_action_handler("stm_defVar", &action::stm_defVar);
|
||||||
Parser::Parser() {
|
parser.set_action_handler("stm_log", &action::stm_log);
|
||||||
mTok.build({
|
|
||||||
{ "\n|\t| |\r", Token::SPACE },
|
parser.set_action_handler("stm_scope_create", &action::stm_scope_create);
|
||||||
{ "var", Token::VAR },
|
parser.set_action_handler("stm_scope_append", &action::stm_scope_append);
|
||||||
{ "class", Token::CLASS_DEF },
|
|
||||||
{ "self", Token::SELF },
|
parser.set_action_handler("scope", &action::scope);
|
||||||
{ "\\{", Token::SCOPE_IN },
|
|
||||||
{ "\\}", Token::SCOPE_OUT },
|
parser.set_action_handler("tmp", &action::tmp);
|
||||||
{ "=", Token::ASSIGN },
|
|
||||||
{ "def", Token::DEF_FUNC },
|
std::string streamStd(stream.read());
|
||||||
{ "<<", Token::PRINT },
|
|
||||||
{ "if", Token::IF },
|
LALR_ASSERT(parser.valid());
|
||||||
{ "else", Token::ELSE },
|
|
||||||
{ "while", Token::WHILE },
|
parser.parse(streamStd.begin(), streamStd.end());
|
||||||
{ "\\(", Token::BRACKET_IN },
|
|
||||||
{ "\\)", Token::BRACKET_OUT },
|
parser.accepted();
|
||||||
{ ",", Token::COMMA },
|
parser.full();
|
||||||
{ "new", Token::NEW },
|
|
||||||
{ "\\.", Token::CHILD },
|
auto scope = (BCgen::StatementScope*) parser.user_data();
|
||||||
{ "return", Token::RETURN },
|
|
||||||
{ "==", Token::EQUAL },
|
return { nullptr, scope };
|
||||||
{ "!=", Token::NOT_EQUAL },
|
|
||||||
{ ">", Token::MORE },
|
|
||||||
{ "<", Token::LESS },
|
|
||||||
{ ">=", Token::QE_OR_MORE },
|
|
||||||
{ "<=", Token::QE_OR_LESS },
|
|
||||||
{ "!", Token::BOOL_NOT },
|
|
||||||
{ "&&", Token::BOOL_AND },
|
|
||||||
{ "\\|\\|", Token::BOOL_OR },
|
|
||||||
{ "\\+", Token::ADD },
|
|
||||||
{ "\\*", Token::MUL },
|
|
||||||
{ "\\-", Token::SUB },
|
|
||||||
{ "/", Token::DIV },
|
|
||||||
{ ";", Token::STM_END },
|
|
||||||
{ "true", Token::CONST_TRUE },
|
|
||||||
{ "false", Token::CONST_FALSE },
|
|
||||||
{ "((\\-)|(\\+))?[0-9]+i?", Token::CONST_INT },
|
|
||||||
{ R"(((\-)|(\+))?([0-9]+)(\.)([0-9]*)?f?)", Token::CONST_FLOAT },
|
|
||||||
{ R"((/\*){\*-\*}*(\*/))", Token::COMMENT_BLOCK },
|
|
||||||
{ R"("{"-"}*")", Token::CONST_STRING },
|
|
||||||
|
|
||||||
{ "([a-z]|[A-Z]|_)+([a-z]|[A-Z]|[0-9]|_)*", Token::ID },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tp::String to_string(const char* stream, tp::alni len) {
|
|
||||||
tp::String out;
|
|
||||||
out.resize(len);
|
|
||||||
tp::memCopy(out.write(), stream, len);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser::Token Parser::tokRead() {
|
|
||||||
Token out;
|
|
||||||
|
|
||||||
if (!tokInputLeft()) {
|
|
||||||
Token out;
|
|
||||||
out.type = Token::NO_TOKEN;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto crs_start = mTok.getCursor();
|
|
||||||
out.type = mTok.readTok();
|
|
||||||
out.token = to_string(crs_start.str(), mTok.lastTokLEn());
|
|
||||||
|
|
||||||
switch (out.type) {
|
|
||||||
case Token::CONST_FALSE: out.boolean = false; break;
|
|
||||||
case Token::CONST_TRUE: out.boolean = true; break;
|
|
||||||
case Token::CONST_INT:
|
|
||||||
{
|
|
||||||
char* p_end;
|
|
||||||
out.integer = std::strtol(out.token.read(), &p_end, 10);
|
|
||||||
DEBUG_ASSERT(out.token.read() != p_end);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Token::CONST_FLOAT:
|
|
||||||
{
|
|
||||||
char* p_end;
|
|
||||||
out.floating = std::strtod(out.token.read(), &p_end);
|
|
||||||
DEBUG_ASSERT(out.token.read() != p_end);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Token::CONST_STRING:
|
|
||||||
{
|
|
||||||
out.str = to_string(crs_start.str() + 1, mTok.lastTokLEn() - 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser::Token Parser::tokLookup() {
|
|
||||||
auto crs = mTok.getCursor();
|
|
||||||
auto out = tokRead();
|
|
||||||
mTok.setCursor(crs);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Parser::tokInputLeft() {
|
|
||||||
auto type = mTok.lookupTok();
|
|
||||||
|
|
||||||
while (mTok.isInputLeft() && type == Token::SPACE || (type >= Token::__END__ && type <= Token::__START__)) {
|
|
||||||
mTok.skipTok();
|
|
||||||
type = mTok.lookupTok();
|
|
||||||
}
|
|
||||||
|
|
||||||
return type != Token::SOURCE_END_TOKEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::tokSkip() {
|
|
||||||
if (!tokInputLeft()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mTok.skipTok();
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser::Tokenizer::Cursor Parser::tokGetCursor() { return mTok.getCursor(); }
|
|
||||||
void Parser::tokSetCursor(Tokenizer::Cursor crs) { mTok.setCursor(crs); }
|
|
||||||
|
|
||||||
Expression* Parser::parseExprCompound() {
|
|
||||||
CHECK(tokRead() == Token::BRACKET_IN, {});
|
|
||||||
auto ret = parseExpr();
|
|
||||||
CHECK_ERROR(ret, {});
|
|
||||||
REQUIRE(tokRead() == Token::BRACKET_OUT, "Expected Closing Bracket", {});
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprNEW() {
|
|
||||||
CHECK(tokRead() == Token::NEW, {});
|
|
||||||
auto name = tokRead();
|
|
||||||
REQUIRE(name == Token::ID, "Expected Identifier", {});
|
|
||||||
|
|
||||||
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected opening brackets", {});
|
|
||||||
REQUIRE(tokRead() == Token::BRACKET_OUT, "Expected closing brackets", {});
|
|
||||||
|
|
||||||
return ExprNew(name.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprLOCAL() {
|
|
||||||
auto local_id_tok = tokRead();
|
|
||||||
if (local_id_tok == Token::ID) {
|
|
||||||
return ExprLocal(local_id_tok.token);
|
|
||||||
} else if (local_id_tok == Token::SELF) {
|
|
||||||
return ExprSelf();
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprCONST() {
|
|
||||||
auto tok = tokRead();
|
|
||||||
switch (tok) {
|
|
||||||
case Token::CONST_FALSE: return ExprConst(false);
|
|
||||||
case Token::CONST_TRUE: return ExprConst(true);
|
|
||||||
case Token::CONST_INT: return ExprConst(tok.integer);
|
|
||||||
case Token::CONST_FLOAT: return ExprConst(tok.floating);
|
|
||||||
case Token::CONST_STRING: return ExprConst(tok.str);
|
|
||||||
default: REQUIRE(0, "not a const Expr", {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprCHILD(Expression* prnt) {
|
|
||||||
CHECK(tokRead() == Token::CHILD, {});
|
|
||||||
auto id = tokRead();
|
|
||||||
REQUIRE(id == Token::ID, "Exprected Identifier", {});
|
|
||||||
return prnt->ExprChild(id.str);
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprCALL(Expression* prnt) {
|
|
||||||
CHECK(tokRead() == Token::BRACKET_IN, {});
|
|
||||||
|
|
||||||
List<Expression*> args;
|
|
||||||
|
|
||||||
READ_ARG:
|
|
||||||
Expression* expr = NULL;
|
|
||||||
auto tok = tokLookup();
|
|
||||||
REQUIRE(tok != Token::NO_TOKEN, "Missing Closing Bracket", {});
|
|
||||||
|
|
||||||
if (tok != Token::BRACKET_OUT) {
|
|
||||||
|
|
||||||
expr = parseExpr();
|
|
||||||
CHECK_ERROR(expr, {
|
|
||||||
for (auto arg : args) {
|
|
||||||
delete arg.data();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
args.pushBack(expr);
|
|
||||||
|
|
||||||
tok = tokLookup();
|
|
||||||
if (tok == Token::COMMA) {
|
|
||||||
tokSkip();
|
|
||||||
goto READ_ARG;
|
|
||||||
} else if (tok != Token::BRACKET_OUT) {
|
|
||||||
for (auto arg : args) {
|
|
||||||
delete arg.data();
|
|
||||||
}
|
|
||||||
REQUIRE(0, "Expected A Closing Bracket", {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tokSkip();
|
|
||||||
|
|
||||||
auto out = prnt->ExprCall({});
|
|
||||||
out->mArgs.reserve(args.length());
|
|
||||||
|
|
||||||
ualni idx = 0;
|
|
||||||
for (auto arg : args) {
|
|
||||||
out->mArgs[idx] = arg.data();
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprAriphm() {
|
|
||||||
|
|
||||||
tp::InitialierList<ExprType> expessions = {
|
|
||||||
ExprType::Compound,
|
|
||||||
ExprType::NEW,
|
|
||||||
ExprType::LOCAL,
|
|
||||||
ExprType::CONST,
|
|
||||||
};
|
|
||||||
|
|
||||||
Expression* left = parseExpr(expessions);
|
|
||||||
CHECK_ERROR(left, {});
|
|
||||||
|
|
||||||
Expression* ret = NULL;
|
|
||||||
|
|
||||||
PARSE:
|
|
||||||
|
|
||||||
Expression* right = NULL;
|
|
||||||
|
|
||||||
auto tok = tokLookup();
|
|
||||||
if (tok.isAriphm()) {
|
|
||||||
tokSkip();
|
|
||||||
|
|
||||||
right = parseExpr(expessions);
|
|
||||||
|
|
||||||
if (mRes.err) {
|
|
||||||
if (ret) {
|
|
||||||
goto PRECEDENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete left;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
CHECK(ret, { delete left; });
|
|
||||||
goto PRECEDENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (tok) {
|
|
||||||
case Token::ADD: ret = ExprAriphm(left, right, OpCode::OBJ_ADD); break;
|
|
||||||
case Token::SUB: ret = ExprAriphm(left, right, OpCode::OBJ_SUB); break;
|
|
||||||
case Token::DIV: ret = ExprAriphm(left, right, OpCode::OBJ_DIV); break;
|
|
||||||
case Token::MUL: ret = ExprAriphm(left, right, OpCode::OBJ_MUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
left = ret;
|
|
||||||
goto PARSE;
|
|
||||||
|
|
||||||
PRECEDENCE:
|
|
||||||
// FIXME: Not Implemented
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprBOOLEAN() {
|
|
||||||
|
|
||||||
tp::InitialierList<ExprType> expessions = {
|
|
||||||
ExprType::Compound, ExprType::NEW, ExprType::LOCAL, ExprType::CONST, ExprType::BOOLEAN_NOT,
|
|
||||||
};
|
|
||||||
|
|
||||||
Expression* left = parseExpr(expessions);
|
|
||||||
CHECK_ERROR(left, {});
|
|
||||||
|
|
||||||
Expression* ret = NULL;
|
|
||||||
|
|
||||||
PARSE:
|
|
||||||
|
|
||||||
Expression* right = NULL;
|
|
||||||
|
|
||||||
auto tok = tokLookup();
|
|
||||||
if (tok.isBoolean()) {
|
|
||||||
tokSkip();
|
|
||||||
|
|
||||||
right = parseExpr(expessions);
|
|
||||||
|
|
||||||
if (mRes.err) {
|
|
||||||
if (ret) {
|
|
||||||
goto PRECEDENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete left;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
CHECK(ret, { delete left; });
|
|
||||||
goto PRECEDENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (tok) {
|
|
||||||
case Token::EQUAL: ret = ExprBool(left, right, OpCode::EQUAL); break;
|
|
||||||
case Token::NOT_EQUAL: ret = ExprBool(left, right, OpCode::NOT_EQUAL); break;
|
|
||||||
case Token::BOOL_AND: ret = ExprBool(left, right, OpCode::AND); break;
|
|
||||||
case Token::BOOL_OR: ret = ExprBool(left, right, OpCode::OR); break;
|
|
||||||
case Token::MORE: ret = ExprBool(left, right, OpCode::MORE); break;
|
|
||||||
case Token::LESS: ret = ExprBool(left, right, OpCode::LESS); break;
|
|
||||||
case Token::QE_OR_MORE: ret = ExprBool(left, right, OpCode::EQUAL_OR_MORE); break;
|
|
||||||
case Token::QE_OR_LESS: ret = ExprBool(left, right, OpCode::EQUAL_OR_LESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
left = ret;
|
|
||||||
goto PARSE;
|
|
||||||
|
|
||||||
PRECEDENCE:
|
|
||||||
// FIXME: Not Implemented
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprBOOLEAN_NOT() {
|
|
||||||
CHECK(tokRead() == Token::BOOL_NOT, {});
|
|
||||||
|
|
||||||
tp::InitialierList<ExprType> exprs = {
|
|
||||||
ExprType::Compound, ExprType::BOOLEAN, ExprType::Ariphm, ExprType::NEW, ExprType::LOCAL, ExprType::CONST,
|
|
||||||
};
|
|
||||||
|
|
||||||
auto out = parseExpr(exprs);
|
|
||||||
CHECK_ERROR(out, {});
|
|
||||||
|
|
||||||
return ExprBoolNot(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExprFUNC() {
|
|
||||||
auto op_tok = tokRead();
|
|
||||||
CHECK(op_tok == Token::ID, {});
|
|
||||||
return ExprFunc(op_tok.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
// passed prnt isno longer responsability of callee
|
|
||||||
// suc : returns top level parent
|
|
||||||
// err : returns NULL
|
|
||||||
Expression* Parser::parseExprChain(Expression* prnt) {
|
|
||||||
|
|
||||||
PARSE_CHAIN:
|
|
||||||
auto tok = tokLookup();
|
|
||||||
|
|
||||||
switch (tok) {
|
|
||||||
case Token::CHILD:
|
|
||||||
{
|
|
||||||
tokRead();
|
|
||||||
|
|
||||||
auto child_id = tokRead();
|
|
||||||
REQUIRE(child_id == Token::ID, "expected an id", { delete prnt; });
|
|
||||||
|
|
||||||
prnt = prnt->ExprChild(child_id.token);
|
|
||||||
goto PARSE_CHAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Token::BRACKET_IN:
|
|
||||||
{
|
|
||||||
|
|
||||||
auto new_prnt = parseExprCALL(prnt);
|
|
||||||
CHECK_ERROR(new_prnt, { delete prnt; });
|
|
||||||
|
|
||||||
if (prnt->mType == Expression::Type::CHILD) {
|
|
||||||
((ExpressionChild*) prnt)->mMethod = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
prnt = new_prnt;
|
|
||||||
goto PARSE_CHAIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return prnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression* Parser::parseExpr(tp::InitialierList<ExprType> expressions) {
|
|
||||||
|
|
||||||
Expression* out = NULL;
|
|
||||||
|
|
||||||
List<Error*> errors;
|
|
||||||
|
|
||||||
for (auto expr_type : expressions) {
|
|
||||||
auto crs = tokGetCursor();
|
|
||||||
switch (expr_type) {
|
|
||||||
case Parser::ExprType::BOOLEAN_NOT: out = parseExprBOOLEAN_NOT(); break;
|
|
||||||
case Parser::ExprType::BOOLEAN: out = parseExprBOOLEAN(); break;
|
|
||||||
case Parser::ExprType::Ariphm: out = parseExprAriphm(); break;
|
|
||||||
case Parser::ExprType::NEW: out = parseExprNEW(); break;
|
|
||||||
case Parser::ExprType::LOCAL: out = parseExprLOCAL(); break;
|
|
||||||
case Parser::ExprType::CONST: out = parseExprCONST(); break;
|
|
||||||
case Parser::ExprType::Compound: out = parseExprCompound(); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tokSetCursor(crs);
|
|
||||||
if (mRes.err) {
|
|
||||||
errors.pushBack(mRes.err);
|
|
||||||
mRes.err = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out) {
|
|
||||||
// check for child expression and calls
|
|
||||||
out = parseExprChain(out);
|
|
||||||
|
|
||||||
// check errors
|
|
||||||
if (mRes.err) {
|
|
||||||
errors.pushBack(mRes.err);
|
|
||||||
mRes.err = NULL;
|
|
||||||
goto ERRORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto err : errors) {
|
|
||||||
delete err.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERRORS:
|
|
||||||
Error* error = NULL;
|
|
||||||
tp::alni max_advanced = 0;
|
|
||||||
for (auto err : errors) {
|
|
||||||
if (err.data()->mAdvanecedIdx && err.data()->mAdvanecedIdx > max_advanced) {
|
|
||||||
max_advanced = err.data()->mAdvanecedIdx;
|
|
||||||
error = err.data();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
mRes.err = new Error(*error);
|
|
||||||
|
|
||||||
for (auto err : errors) {
|
|
||||||
delete err.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
REQUIRE(0, "Expected and expression", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmCall() {
|
|
||||||
|
|
||||||
Expression* expr = parseExpr();
|
|
||||||
CHECK_ERROR(expr, {});
|
|
||||||
|
|
||||||
REQUIRE(expr->mType == Expression::Type::CALL, "expression statement can only be function call", { delete expr; });
|
|
||||||
|
|
||||||
if (tokRead() != Token::STM_END) {
|
|
||||||
delete expr;
|
|
||||||
REQUIRE(0, "Expected End Of Statement", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return StmIgnore(expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmDefFunc() {
|
|
||||||
CHECK(tokRead() == Token::DEF_FUNC, {});
|
|
||||||
List<tp::String> args;
|
|
||||||
auto name = tokRead();
|
|
||||||
REQUIRE(name == Token::ID, "Expected an Identifier", {});
|
|
||||||
|
|
||||||
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
|
|
||||||
|
|
||||||
READ_ARG:
|
|
||||||
auto tok = tokLookup();
|
|
||||||
|
|
||||||
REQUIRE(tok != Token::NO_TOKEN, "Missing Closing Bracket", {});
|
|
||||||
|
|
||||||
if (tok == Token::ID) {
|
|
||||||
args.pushBack(tok.token);
|
|
||||||
tokSkip();
|
|
||||||
tok = tokLookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tok == Token::COMMA) {
|
|
||||||
tokSkip();
|
|
||||||
goto READ_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
REQUIRE(tok == Token::BRACKET_OUT, "Expected Closing Bracket", {});
|
|
||||||
tokSkip();
|
|
||||||
|
|
||||||
auto func_def = StmDefFunc(name.token, {}, {});
|
|
||||||
|
|
||||||
func_def->mArgs.reserve(args.length());
|
|
||||||
|
|
||||||
ualni idx = 0;
|
|
||||||
for (auto iter : args) {
|
|
||||||
func_def->mArgs[idx] = iter.data();
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatementScope* scope = parseScope(true);
|
|
||||||
CHECK_ERROR(scope, { delete func_def; });
|
|
||||||
|
|
||||||
func_def->mStatements.reserve(scope->mStatements.size());
|
|
||||||
|
|
||||||
idx = 0;
|
|
||||||
for (auto stm : scope->mStatements) {
|
|
||||||
func_def->mStatements[idx] = stm.data();
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete scope;
|
|
||||||
return func_def;
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmDefLocal() {
|
|
||||||
CHECK(tokRead() == Token::VAR, {});
|
|
||||||
|
|
||||||
auto tok = tokRead();
|
|
||||||
REQUIRE(tok == Token::ID, "Expected an Identifier", {});
|
|
||||||
REQUIRE(tokRead() == Token::ASSIGN, "Expected an assigment", {});
|
|
||||||
|
|
||||||
auto expr = parseExpr();
|
|
||||||
CHECK_ERROR(expr, {});
|
|
||||||
|
|
||||||
if (tokRead() != Token::STM_END) {
|
|
||||||
delete expr;
|
|
||||||
REQUIRE(0, "Expected End Of Statement", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return StmDefLocal(tok.token, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmReturn() {
|
|
||||||
CHECK(tokRead() == Token::RETURN, {});
|
|
||||||
auto crs = tokGetCursor();
|
|
||||||
|
|
||||||
auto expr = parseExpr();
|
|
||||||
if (mRes.err) {
|
|
||||||
tokSetCursor(crs);
|
|
||||||
delete mRes.err;
|
|
||||||
mRes.err = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tokRead() != Token::STM_END) {
|
|
||||||
if (expr) delete expr;
|
|
||||||
REQUIRE(0, "Expected End Of Statement", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return expr ? StmReturn(expr) : StmReturn();
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmPrint() {
|
|
||||||
CHECK(tokRead() == Token::PRINT, {});
|
|
||||||
auto expr = parseExpr();
|
|
||||||
CHECK_ERROR(expr, {});
|
|
||||||
|
|
||||||
if (tokRead() != Token::STM_END) {
|
|
||||||
delete expr;
|
|
||||||
REQUIRE(0, "Expected End Of Statement", {});
|
|
||||||
}
|
|
||||||
return StmPrint(expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmIf() {
|
|
||||||
CHECK(tokRead() == Token::IF, {});
|
|
||||||
|
|
||||||
// single if
|
|
||||||
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
|
|
||||||
auto expr = parseExpr();
|
|
||||||
CHECK_ERROR(expr, {});
|
|
||||||
|
|
||||||
if (tokRead() != Token::BRACKET_OUT) {
|
|
||||||
delete expr;
|
|
||||||
REQUIRE(0, "Expected Closing Bracket", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ontrue = parseScope(false);
|
|
||||||
CHECK_ERROR(ontrue, {});
|
|
||||||
|
|
||||||
// if-else
|
|
||||||
auto crs = tokGetCursor();
|
|
||||||
if (tokRead() == Token::ELSE) {
|
|
||||||
StatementScope* onfalse = parseScope(false);
|
|
||||||
CHECK_ERROR(onfalse, {
|
|
||||||
delete ontrue;
|
|
||||||
delete expr;
|
|
||||||
});
|
|
||||||
|
|
||||||
return StmIf(expr, ontrue, onfalse);
|
|
||||||
}
|
|
||||||
tokSetCursor(crs);
|
|
||||||
|
|
||||||
return StmIf(expr, ontrue, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmWhile() {
|
|
||||||
CHECK(tokRead() == Token::WHILE, {});
|
|
||||||
|
|
||||||
REQUIRE(tokRead() == Token::BRACKET_IN, "Expected Opening Bracket", {});
|
|
||||||
auto expr = parseExpr();
|
|
||||||
CHECK_ERROR(expr, {});
|
|
||||||
|
|
||||||
if (tokRead() != Token::BRACKET_OUT) {
|
|
||||||
delete expr;
|
|
||||||
REQUIRE(0, "Expected Closing Bracket", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto scope = parseScope(false);
|
|
||||||
CHECK_ERROR(scope, {});
|
|
||||||
|
|
||||||
return StmWhile(expr, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmCopy() {
|
|
||||||
auto left = parseExpr();
|
|
||||||
CHECK_ERROR(left, {});
|
|
||||||
|
|
||||||
CHECK(tokRead() == Token::ASSIGN, {});
|
|
||||||
|
|
||||||
auto right = parseExpr();
|
|
||||||
CHECK_ERROR(right, { delete left; });
|
|
||||||
|
|
||||||
if (tokRead() != Token::STM_END) {
|
|
||||||
delete left;
|
|
||||||
delete right;
|
|
||||||
REQUIRE(0, "Expected End Of Statement", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return StmCopy(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStmClassDef() {
|
|
||||||
CHECK(tokRead() == Token::CLASS_DEF, {});
|
|
||||||
|
|
||||||
auto id = tokRead();
|
|
||||||
REQUIRE(id == Token::ID, "Expected an Identifier", {});
|
|
||||||
|
|
||||||
auto scope = parseScope(true);
|
|
||||||
CHECK_ERROR(scope, {});
|
|
||||||
|
|
||||||
return StmClassDef(id.token, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement* Parser::parseStm(tp::InitialierList<StmType> stm_types) {
|
|
||||||
Statement* out = NULL;
|
|
||||||
|
|
||||||
List<Error*> errors;
|
|
||||||
|
|
||||||
for (auto stm_type : stm_types) {
|
|
||||||
auto crs = tokGetCursor();
|
|
||||||
switch (stm_type) {
|
|
||||||
case StmType::DefFunc: out = parseStmDefFunc(); break;
|
|
||||||
case StmType::DefLocal: out = parseStmDefLocal(); break;
|
|
||||||
case StmType::Return: out = parseStmReturn(); break;
|
|
||||||
case StmType::Print: out = parseStmPrint(); break;
|
|
||||||
case StmType::If: out = parseStmIf(); break;
|
|
||||||
case StmType::While: out = parseStmWhile(); break;
|
|
||||||
case StmType::Copy: out = parseStmCopy(); break;
|
|
||||||
case StmType::Call: out = parseStmCall(); break;
|
|
||||||
case StmType::CLASS_DEF: out = parseStmClassDef(); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tokSetCursor(crs);
|
|
||||||
if (mRes.err) {
|
|
||||||
errors.pushBack(mRes.err);
|
|
||||||
mRes.err = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out) {
|
|
||||||
for (auto err : errors) {
|
|
||||||
delete err.data();
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error* error = NULL;
|
|
||||||
tp::alni max_advanced = 0;
|
|
||||||
for (auto err : errors) {
|
|
||||||
if (err.data()->mAdvanecedIdx && max_advanced < err.data()->mAdvanecedIdx) {
|
|
||||||
max_advanced = err.data()->mAdvanecedIdx;
|
|
||||||
error = err.data();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
mRes.err = new Error(*error);
|
|
||||||
|
|
||||||
for (auto err : errors) {
|
|
||||||
delete err.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
REQUIRE(0, "Exprected A Statement", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
StatementScope* Parser::parseScope(bool aPushToScopeStack) {
|
|
||||||
CHECK(tokRead() == Token::SCOPE_IN, {});
|
|
||||||
|
|
||||||
auto out = new StatementScope({}, aPushToScopeStack);
|
|
||||||
List<Statement*> stms;
|
|
||||||
|
|
||||||
READ_STM:
|
|
||||||
auto crs = tokGetCursor();
|
|
||||||
auto tok = tokRead();
|
|
||||||
|
|
||||||
if (tok == Token::NO_TOKEN) {
|
|
||||||
delete out;
|
|
||||||
for (auto stm : stms) {
|
|
||||||
delete stm.data();
|
|
||||||
}
|
|
||||||
REQUIRE(0, "Missing Scope Closing Bracket", {});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tok != Token::SCOPE_OUT) {
|
|
||||||
tokSetCursor(crs);
|
|
||||||
|
|
||||||
auto stm = parseStm();
|
|
||||||
CHECK_ERROR(stm, {
|
|
||||||
delete out;
|
|
||||||
for (auto stm : stms) {
|
|
||||||
delete stm.data();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
stms.pushBack(stm);
|
|
||||||
|
|
||||||
goto READ_STM;
|
|
||||||
}
|
|
||||||
|
|
||||||
out->mStatements.reserve(stms.length());
|
|
||||||
|
|
||||||
ualni idx = 0;
|
|
||||||
for (auto stm : stms) {
|
|
||||||
out->mStatements[idx] = stm.data();
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser::Resault Parser::parse(const tp::String& oscript) {
|
|
||||||
mTok.bindSource(oscript.read());
|
|
||||||
mTok.reset();
|
|
||||||
|
|
||||||
mRes.scope = new StatementScope({}, true);
|
|
||||||
|
|
||||||
List<Statement*> stms;
|
|
||||||
do {
|
|
||||||
auto stm = parseStm();
|
|
||||||
|
|
||||||
if (mRes.err || !stm) { // catch
|
|
||||||
delete mRes.scope;
|
|
||||||
mRes.scope = NULL;
|
|
||||||
for (auto stm : stms) {
|
|
||||||
delete stm.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
return mRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
stms.pushBack(stm);
|
|
||||||
|
|
||||||
} while (tokInputLeft());
|
|
||||||
|
|
||||||
mRes.scope->mStatements.reserve(stms.length());
|
|
||||||
|
|
||||||
ualni idx = 0;
|
|
||||||
for (auto stm : stms) {
|
|
||||||
mRes.scope->mStatements[idx] = stm.data();
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mRes;
|
|
||||||
}
|
}
|
||||||
|
|
@ -13,7 +13,6 @@ namespace obj {
|
||||||
struct ExpressionCall;
|
struct ExpressionCall;
|
||||||
|
|
||||||
struct Expression {
|
struct Expression {
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
NONE,
|
NONE,
|
||||||
NEW,
|
NEW,
|
||||||
|
|
|
||||||
|
|
@ -3,193 +3,43 @@
|
||||||
#include "compiler/statement.h"
|
#include "compiler/statement.h"
|
||||||
#include "compiler/expression.h"
|
#include "compiler/expression.h"
|
||||||
|
|
||||||
#include "Tokenizer.hpp"
|
|
||||||
|
|
||||||
namespace obj {
|
namespace obj {
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
|
|
||||||
struct Token {
|
|
||||||
|
|
||||||
tp::String token;
|
|
||||||
|
|
||||||
tp::alni integer;
|
|
||||||
tp::alnf floating;
|
|
||||||
bool boolean;
|
|
||||||
tp::String str;
|
|
||||||
|
|
||||||
enum TokType : tp::alni {
|
|
||||||
__START__ = 0,
|
|
||||||
ID,
|
|
||||||
CONST_INT,
|
|
||||||
CONST_FLOAT,
|
|
||||||
CONST_STRING,
|
|
||||||
SCOPE_IN,
|
|
||||||
SCOPE_OUT,
|
|
||||||
ASSIGN,
|
|
||||||
DEF_FUNC,
|
|
||||||
PRINT,
|
|
||||||
IF,
|
|
||||||
ELSE,
|
|
||||||
WHILE,
|
|
||||||
BRACKET_IN,
|
|
||||||
BRACKET_OUT,
|
|
||||||
COMMA,
|
|
||||||
NEW,
|
|
||||||
CHILD,
|
|
||||||
RETURN,
|
|
||||||
EQUAL,
|
|
||||||
NOT_EQUAL,
|
|
||||||
MORE,
|
|
||||||
LESS,
|
|
||||||
QE_OR_MORE,
|
|
||||||
QE_OR_LESS,
|
|
||||||
BOOL_NOT,
|
|
||||||
BOOL_AND,
|
|
||||||
BOOL_OR,
|
|
||||||
ADD,
|
|
||||||
MUL,
|
|
||||||
SUB,
|
|
||||||
DIV,
|
|
||||||
QUOTES,
|
|
||||||
CONST_TRUE,
|
|
||||||
CONST_FALSE,
|
|
||||||
STM_END,
|
|
||||||
SPACE,
|
|
||||||
VAR,
|
|
||||||
CLASS_DEF,
|
|
||||||
SELF,
|
|
||||||
COMMENT_BLOCK,
|
|
||||||
__END__,
|
|
||||||
NO_TOKEN,
|
|
||||||
FAILED,
|
|
||||||
SOURCE_END_TOKEN,
|
|
||||||
} type;
|
|
||||||
|
|
||||||
operator TokType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isAriphm();
|
|
||||||
bool isBoolean();
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef tp::SimpleTokenizer<char, Token::TokType, Token::NO_TOKEN, Token::FAILED, Token::SOURCE_END_TOKEN> Tokenizer;
|
|
||||||
Tokenizer mTok;
|
|
||||||
|
|
||||||
enum class ExprType {
|
|
||||||
BOOLEAN_NOT = 0,
|
|
||||||
BOOLEAN,
|
|
||||||
Ariphm,
|
|
||||||
NEW,
|
|
||||||
LOCAL,
|
|
||||||
CONST,
|
|
||||||
Compound
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class StmType {
|
|
||||||
DefFunc = 0,
|
|
||||||
DefLocal,
|
|
||||||
Return,
|
|
||||||
Print,
|
|
||||||
If,
|
|
||||||
While,
|
|
||||||
Copy,
|
|
||||||
Call,
|
|
||||||
CLASS_DEF
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Parser() = default;
|
||||||
Parser();
|
|
||||||
|
|
||||||
struct Error {
|
struct Error {
|
||||||
tp::String mDescr = "No Description";
|
tp::String mDescription = "No Description";
|
||||||
tp::alni mAdvanecedIdx = 0;
|
tp::alni mAdvancedIdx = 0;
|
||||||
|
|
||||||
Error() {}
|
Error() = default;
|
||||||
Error(tp::String descr, tp::alni idx) {
|
Error(const tp::String& description, tp::alni idx) {
|
||||||
mDescr = descr;
|
mDescription = description;
|
||||||
mAdvanecedIdx = idx;
|
mAdvancedIdx = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
tp::Pair<tp::alni, tp::alni> get_err_location(const char* stream) {
|
tp::Pair<tp::alni, tp::alni> getErrorLocation(const char* stream) const {
|
||||||
tp::alni line = 1;
|
tp::alni line = 1;
|
||||||
tp::alni colomn = 1;
|
tp::alni column = 1;
|
||||||
|
|
||||||
//assert(mAdvanecedIdx);
|
for (auto i : tp::Range(mAdvancedIdx)) {
|
||||||
|
|
||||||
for (auto i : tp::Range(mAdvanecedIdx)) {
|
|
||||||
if (stream[i] == '\n') {
|
if (stream[i] == '\n') {
|
||||||
colomn = 0;
|
column = 0;
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
colomn++;
|
column++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { line, colomn };
|
return { line, column };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Resault {
|
struct Result {
|
||||||
Error* err = NULL;
|
Error* err = nullptr;
|
||||||
obj::BCgen::StatementScope* scope = NULL;
|
obj::BCgen::StatementScope* scope = nullptr;
|
||||||
} mRes;
|
};
|
||||||
|
|
||||||
Resault parse(const tp::String& stream);
|
Result parse(const tp::String& stream);
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Token tokRead();
|
|
||||||
Token tokLookup();
|
|
||||||
void tokSkip();
|
|
||||||
bool tokInputLeft();
|
|
||||||
Tokenizer::Cursor tokGetCursor();
|
|
||||||
void tokSetCursor(Tokenizer::Cursor);
|
|
||||||
|
|
||||||
BCgen::Expression* parseExprCompound();
|
|
||||||
BCgen::Expression* parseExprNEW();
|
|
||||||
BCgen::Expression* parseExprLOCAL();
|
|
||||||
BCgen::Expression* parseExprCONST();
|
|
||||||
BCgen::Expression* parseExprCHILD(BCgen::Expression* prnt);
|
|
||||||
BCgen::Expression* parseExprCALL(BCgen::Expression* prnt);
|
|
||||||
BCgen::Expression* parseExprAriphm();
|
|
||||||
BCgen::Expression* parseExprBOOLEAN();
|
|
||||||
BCgen::Expression* parseExprBOOLEAN_NOT();
|
|
||||||
BCgen::Expression* parseExprFUNC();
|
|
||||||
BCgen::Expression* parseExprChain(BCgen::Expression* prnt);
|
|
||||||
|
|
||||||
BCgen::Expression* parseExpr(tp::InitialierList<ExprType> expressions = {
|
|
||||||
ExprType::BOOLEAN_NOT,
|
|
||||||
ExprType::BOOLEAN,
|
|
||||||
ExprType::Ariphm,
|
|
||||||
ExprType::NEW,
|
|
||||||
ExprType::LOCAL,
|
|
||||||
ExprType::CONST,
|
|
||||||
});
|
|
||||||
|
|
||||||
BCgen::Statement* parseStmCall();
|
|
||||||
BCgen::Statement* parseStmDefFunc();
|
|
||||||
BCgen::Statement* parseStmDefLocal();
|
|
||||||
BCgen::Statement* parseStmReturn();
|
|
||||||
BCgen::Statement* parseStmPrint();
|
|
||||||
BCgen::Statement* parseStmIf();
|
|
||||||
BCgen::Statement* parseStmWhile();
|
|
||||||
BCgen::Statement* parseStmCopy();
|
|
||||||
BCgen::Statement* parseStmClassDef();
|
|
||||||
|
|
||||||
BCgen::Statement* parseStm(tp::InitialierList<StmType> stm_types = {
|
|
||||||
StmType::DefFunc,
|
|
||||||
StmType::DefLocal,
|
|
||||||
StmType::Return,
|
|
||||||
StmType::Print,
|
|
||||||
StmType::If,
|
|
||||||
StmType::While,
|
|
||||||
StmType::Copy,
|
|
||||||
StmType::Call,
|
|
||||||
StmType::CLASS_DEF
|
|
||||||
});
|
|
||||||
|
|
||||||
BCgen::StatementScope* parseScope(bool aPushToScopeStack);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
16
Objects/tests/TestParser.cpp
Normal file
16
Objects/tests/TestParser.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
#include "Testing.hpp"
|
||||||
|
|
||||||
|
#include "parser/parser.h"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
using namespace obj;
|
||||||
|
|
||||||
|
TEST_DEF_STATIC(Basic) {
|
||||||
|
Parser parser;
|
||||||
|
|
||||||
|
String stream = "{ var i; print false; }";
|
||||||
|
auto res = parser.parse(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_DEF(Parser) { testBasic(); }
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
using namespace obj;
|
using namespace obj;
|
||||||
|
|
||||||
|
void testParser();
|
||||||
void testCore();
|
void testCore();
|
||||||
void testPrimitives();
|
void testPrimitives();
|
||||||
void testInterpreter();
|
void testInterpreter();
|
||||||
|
|
@ -15,6 +16,11 @@ int main() {
|
||||||
tp::ModuleManifest* deps[] = { &gModuleObjects, nullptr };
|
tp::ModuleManifest* deps[] = { &gModuleObjects, nullptr };
|
||||||
tp::ModuleManifest module("ObjectsTests", nullptr, nullptr, deps);
|
tp::ModuleManifest module("ObjectsTests", nullptr, nullptr, deps);
|
||||||
|
|
||||||
|
if (module.initialize()) {
|
||||||
|
testParser();
|
||||||
|
module.deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
if (module.initialize()) {
|
if (module.initialize()) {
|
||||||
testCore();
|
testCore();
|
||||||
module.deinitialize();
|
module.deinitialize();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue