parser error handling

This commit is contained in:
IlyaShurupov 2024-03-06 17:31:17 +03:00 committed by Ilusha
parent fdb861b299
commit 49c67eb028
10 changed files with 119 additions and 72 deletions

3
.gitmodules vendored
View file

@ -16,3 +16,6 @@
[submodule "Externals/lua"] [submodule "Externals/lua"]
path = Externals/lua path = Externals/lua
url = https://github.com/lua/lua.git url = https://github.com/lua/lua.git
[submodule "Externals/lalr"]
path = Externals/lalr
url = https://github.com/IlyaShurupov/lalr.git

View file

@ -22,8 +22,9 @@ add_executable(osg ./applications/GUI.cpp ./applications/GUIEntry.cpp)
#target_link_libraries(osi ${PROJECT_NAME}) #target_link_libraries(osi ${PROJECT_NAME})
target_link_libraries(osg ${PROJECT_NAME} Graphics Imgui) target_link_libraries(osg ${PROJECT_NAME} Graphics Imgui)
file(COPY "rsc/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
### -------------------------- Tests -------------------------- ### ### -------------------------- Tests -------------------------- ###
enable_testing()
file(GLOB TEST_SOURCES "./tests/*.cpp" "./tests/*/*.cpp") file(GLOB TEST_SOURCES "./tests/*.cpp" "./tests/*/*.cpp")
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES}) add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils) target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)

View file

@ -29,7 +29,8 @@ namespace ImGui {
void ApplyStyle(tp::halnf dpmm, float font_size_mm = 5, float ui_scale = 1); void ApplyStyle(tp::halnf dpmm, float font_size_mm = 5, float ui_scale = 1);
}; };
ImGui::PopupData ImGui::HoverPopupBegin(const char* str_id, tp::Vec2F size, tp::Vec2F pos_p, ImGuiPopupFlags popup_flags) { ImGui::PopupData
ImGui::HoverPopupBegin(const char* str_id, tp::Vec2F size, tp::Vec2F pos_p, ImGuiPopupFlags popup_flags) {
ImGui::PopupData out; ImGui::PopupData out;
out.ishovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); out.ishovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
@ -69,7 +70,10 @@ void ImGui::HoverPopupEnd(ImGui::PopupData& in) {
return; return;
} }
in.ishovered |= IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_ChildWindows); in.ishovered |= IsWindowHovered(
ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem |
ImGuiHoveredFlags_ChildWindows
);
tp::Vec2F mousepos = { ImGui::GetMousePos().x, ImGui::GetMousePos().y }; tp::Vec2F mousepos = { ImGui::GetMousePos().x, ImGui::GetMousePos().y };
tp::halnf tollerance = 10; tp::halnf tollerance = 10;
@ -876,7 +880,12 @@ void obj::ObjectsGUI::explorer() {
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::BeginChild("child_path", { 0, 45 }, false, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_HorizontalScrollbar); ImGui::BeginChild(
"child_path",
{ 0, 45 },
false,
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_HorizontalScrollbar
);
tp::List<ViewStackNode*> rev_path; tp::List<ViewStackNode*> rev_path;
for (auto childo = mViewStack.last(); childo; childo = childo->prev) { for (auto childo = mViewStack.last(); childo; childo = childo->prev) {
rev_path.pushBack(&childo->data); rev_path.pushBack(&childo->data);
@ -994,7 +1003,7 @@ void obj::ObjectsGUI::properties(const obj::ObjectType* type, bool top_of_tree_v
assert(type); assert(type);
assert(mActive); assert(mActive);
assert(mActive->type == type); if (mActive->type != type) return;
ImGui::Text(" RefCount : %i", obj::NDO->getrefc(mActive)); ImGui::Text(" RefCount : %i", obj::NDO->getrefc(mActive));

View file

@ -1,8 +1,6 @@
#include "Private.hpp" #include "Private.hpp"
#include <parser/parser.h>
using namespace obj::BCgen; using namespace obj::BCgen;
typedef lalr::ParserNode<SymbolType> Node; typedef lalr::ParserNode<SymbolType> Node;
@ -12,23 +10,19 @@ static UserData scope(const UserData* start, const Node*, size_t) { return start
static UserData scope_empty(const UserData*, const Node*, size_t) { return new StatementScope({}, true); } static UserData scope_empty(const UserData*, const Node*, size_t) { return new StatementScope({}, true); }
static UserData stm_list_append(const UserData* start, const Node*, size_t) { static UserData stm_list_append(const UserData* start, const Node*, size_t) {
auto scope = (StatementScope*) start[0]; auto scope = (StatementScope*) start[0].statement;
auto stm = (Statement*) start[1]; scope->mStatements.append(start[1].statement);
scope->mStatements.append(stm);
return scope; return scope;
} }
static UserData stm_list_create(const UserData* start, const Node*, size_t) { static UserData stm_list_create(const UserData* start, const Node*, size_t) {
return new StatementScope({ (Statement*) start[0] }, true); return new StatementScope({ start[0].statement }, true);
} }
static UserData stm_log(const UserData* start, const Node*, size_t) { static UserData stm_log(const UserData* start, const Node*, size_t) { return new StatementPrint(start[1].expression); }
auto expr = (Expression*) (start[1]);
return new StatementPrint(expr);
}
static UserData stm_assign(const UserData* start, const Node*, size_t) { static UserData stm_assign(const UserData* start, const Node*, size_t) {
return new StatementCopy((Expression*) start[0], (Expression*) start[2]); return new StatementCopy(start[0].expression, start[2].expression);
} }
static UserData stm_var_def_new_type(const UserData*, const Node* nodes, size_t) { static UserData stm_var_def_new_type(const UserData*, const Node* nodes, size_t) {
@ -36,51 +30,53 @@ static UserData stm_var_def_new_type(const UserData*, const Node* nodes, size_t)
} }
static UserData stm_var_def_assign(const UserData* start, const Node* nodes, size_t) { static UserData stm_var_def_assign(const UserData* start, const Node* nodes, size_t) {
return new StatementLocalDef((char*) nodes[1].lexeme().c_str(), (Expression*) start[3]); return new StatementLocalDef((char*) nodes[1].lexeme().c_str(), start[3].expression);
} }
static UserData stm_return(const UserData* start, const Node*, size_t length) { static UserData stm_return(const UserData* start, const Node*, size_t length) {
if (length == 2) { if (length == 2) {
return new StatementReturn((Expression*) start[1]); return new StatementReturn(start[1].expression);
} }
return new StatementReturn(); return new StatementReturn();
} }
static UserData stm_ignore(const UserData* start, const Node*, size_t) { static UserData stm_ignore(const UserData* start, const Node*, size_t) {
return new StatementIgnore((Expression*) start[0]); return new StatementIgnore(start[0].expression);
} }
static UserData stm_def_class(const UserData* start, const Node* nodes, size_t) { static UserData stm_def_class(const UserData* start, const Node* nodes, size_t) {
auto newClass = new StatementClassDef((char*) nodes[1].lexeme().c_str(), (StatementScope*) start[2]); auto newClass = new StatementClassDef((char*) nodes[1].lexeme().c_str(), (StatementScope*) start[2].statement);
return newClass; return newClass;
} }
static UserData stm_def_method(const UserData* start, const Node* nodes, size_t) { static UserData stm_def_method(const UserData* start, const Node* nodes, size_t) {
auto method = new StatementFuncDef((char*) nodes[1].lexeme().c_str()); auto method = new StatementFuncDef((char*) nodes[1].lexeme().c_str());
method->mStatements = (StatementScope*) start[5]; method->mStatements = (StatementScope*) start[5].statement;
auto args = (tp::Buffer<tp::String>*) start[3]; auto args = start[3].arguments;
method->mArgs = *args; method->mArgs = *args;
delete args; delete args;
return method; return method;
} }
static UserData stm_if(const UserData* start, const Node*, size_t length) { static UserData stm_if(const UserData* start, const Node*, size_t length) {
if (length == 5) return new StatementIf((Expression*) start[2], (StatementScope*) start[4], nullptr); if (length == 5) return new StatementIf(start[2].expression, (StatementScope*) start[4].statement, nullptr);
return new StatementIf((Expression*) start[2], (StatementScope*) start[4], (StatementScope*) start[6]); return new StatementIf(
start[2].expression, (StatementScope*) start[4].statement, (StatementScope*) start[6].statement
);
} }
static UserData stm_while_loop(const UserData* start, const Node*, size_t) { static UserData stm_while_loop(const UserData* start, const Node*, size_t) {
return new StatementWhile((Expression*) start[2], (StatementScope*) start[4]); return new StatementWhile(start[2].expression, (StatementScope*) start[4].statement);
} }
static UserData stm_break(const UserData*, const Node*, size_t) { static UserData stm_break(const UserData*, const Node*, size_t) {
ASSERT(0); ASSERT(0);
// todo : implement break // todo : implement break
return nullptr; return {};
} }
static UserData id_list_append(const UserData* start, const Node* nodes, size_t) { static UserData id_list_append(const UserData* start, const Node* nodes, size_t) {
auto list = (tp::Buffer<tp::String>*) start[0]; auto list = start[0].arguments;
list->append((char*) nodes[1].lexeme().c_str()); list->append((char*) nodes[1].lexeme().c_str());
return list; return list;
} }
@ -90,82 +86,78 @@ static UserData id_list_create(const UserData*, const Node* nodes, size_t) {
} }
static UserData expr_function(const UserData* start, const Node*, size_t) { static UserData expr_function(const UserData* start, const Node*, size_t) {
auto expr = (Expression*) (start[0]); auto expr = start[0].expression;
auto args = (ExpressionList*) (start[2]); auto args = (ExpressionList*) start[2].expression;
return expr->ExprCall(args); return expr->ExprCall(args);
} }
static UserData expr_method(const UserData* start, const Node* nodes, size_t) { static UserData expr_method(const UserData* start, const Node* nodes, size_t) {
auto expr = (Expression*) (start[0]); auto expr = start[0].expression;
auto args = (ExpressionList*) (start[4]); auto args = (ExpressionList*) (start[4].expression);
auto childId = nodes[1].lexeme(); auto childId = nodes[1].lexeme();
auto method = new ExpressionChild(expr, (char*) childId.c_str()); auto method = new ExpressionChild(expr, (char*) childId.c_str());
return method->ExprCall(args); return method->ExprCall(args);
} }
static UserData expr_list_append(const UserData* start, const Node*, size_t) { static UserData expr_list_append(const UserData* start, const Node*, size_t) {
auto list = (ExpressionList*) start[0]; auto list = (ExpressionList*) start[0].expression;
auto expr = (Expression*) start[2]; auto expr = start[2].expression;
list->mItems.append(expr); list->mItems.append(expr);
return list; return list;
} }
static UserData expr_list_create(const UserData* start, const Node*, size_t) { static UserData expr_list_create(const UserData* start, const Node*, size_t) {
auto exprList = new ExpressionList(); auto exprList = new ExpressionList();
exprList->mItems.append((Expression*) start[0]); exprList->mItems.append(start[0].expression);
return exprList; return exprList;
} }
static UserData expr_child(const UserData* start, const Node* nodes, size_t) { static UserData expr_child(const UserData* start, const Node* nodes, size_t) {
return new ExpressionChild((Expression*) start[0], (char*) nodes[2].lexeme().c_str()); return new ExpressionChild(start[0].expression, (char*) nodes[2].lexeme().c_str());
} }
static UserData expr_bool_eq(const UserData* start, const Node*, size_t) { static UserData expr_bool_eq(const UserData* start, const Node*, size_t) {
return new ExpressionBoolean((Expression*) start[0], (Expression*) start[2], ExpressionBoolean::BoolType::EQUAL); return new ExpressionBoolean(start[0].expression, start[2].expression, ExpressionBoolean::BoolType::EQUAL);
} }
static UserData expr_bool_negate(const UserData* start, const Node*, size_t) { static UserData expr_bool_negate(const UserData* start, const Node*, size_t) {
return new ExpressionBoolean((Expression*) start[1]); return new ExpressionBoolean(start[1].expression);
} }
static UserData expr_bool_neq(const UserData* start, const Node*, size_t) { static UserData expr_bool_neq(const UserData* start, const Node*, size_t) {
return new ExpressionBoolean((Expression*) start[0], (Expression*) start[2], ExpressionBoolean::BoolType::NOT_EQUAL); return new ExpressionBoolean(start[0].expression, start[2].expression, ExpressionBoolean::BoolType::NOT_EQUAL);
} }
static UserData expr_bool_grater(const UserData* start, const Node*, size_t) { static UserData expr_bool_grater(const UserData* start, const Node*, size_t) {
return new ExpressionBoolean((Expression*) start[0], (Expression*) start[2], ExpressionBoolean::BoolType::MORE); return new ExpressionBoolean(start[0].expression, start[2].expression, ExpressionBoolean::BoolType::MORE);
} }
static UserData expr_bool_lesser(const UserData* start, const Node*, size_t) { static UserData expr_bool_lesser(const UserData* start, const Node*, size_t) {
return new ExpressionBoolean((Expression*) start[0], (Expression*) start[2], ExpressionBoolean::BoolType::LESS); return new ExpressionBoolean(start[0].expression, start[2].expression, ExpressionBoolean::BoolType::LESS);
} }
static UserData expr_bool_grater_eq(const UserData* start, const Node*, size_t) { static UserData expr_bool_grater_eq(const UserData* start, const Node*, size_t) {
return new ExpressionBoolean( return new ExpressionBoolean(start[0].expression, start[2].expression, ExpressionBoolean::BoolType::EQUAL_OR_MORE);
(Expression*) start[0], (Expression*) start[2], ExpressionBoolean::BoolType::EQUAL_OR_MORE
);
} }
static UserData expr_bool_lesser_eq(const UserData* start, const Node*, size_t) { static UserData expr_bool_lesser_eq(const UserData* start, const Node*, size_t) {
return new ExpressionBoolean( return new ExpressionBoolean(start[0].expression, start[2].expression, ExpressionBoolean::BoolType::EQUAL_OR_LESS);
(Expression*) start[0], (Expression*) start[2], ExpressionBoolean::BoolType::EQUAL_OR_LESS
);
} }
static UserData expr_add(const UserData* start, const Node*, size_t) { static UserData expr_add(const UserData* start, const Node*, size_t) {
return new ExpressionArithmetics((Expression*) start[0], (Expression*) start[2], obj::OpCode::OBJ_ADD); return new ExpressionArithmetics(start[0].expression, start[2].expression, obj::OpCode::OBJ_ADD);
} }
static UserData expr_subtract(const UserData* start, const Node*, size_t) { static UserData expr_subtract(const UserData* start, const Node*, size_t) {
return new ExpressionArithmetics((Expression*) start[0], (Expression*) start[2], obj::OpCode::OBJ_SUB); return new ExpressionArithmetics(start[0].expression, start[2].expression, obj::OpCode::OBJ_SUB);
} }
static UserData expr_multiply(const UserData* start, const Node*, size_t) { static UserData expr_multiply(const UserData* start, const Node*, size_t) {
return new ExpressionArithmetics((Expression*) start[0], (Expression*) start[2], obj::OpCode::OBJ_MUL); return new ExpressionArithmetics(start[0].expression, start[2].expression, obj::OpCode::OBJ_MUL);
} }
static UserData expr_divide(const UserData* start, const Node*, size_t) { static UserData expr_divide(const UserData* start, const Node*, size_t) {
return new ExpressionArithmetics((Expression*) start[0], (Expression*) start[2], obj::OpCode::OBJ_DIV); return new ExpressionArithmetics(start[0].expression, start[2].expression, obj::OpCode::OBJ_DIV);
} }
static UserData expr_compound(const UserData* start, const Node*, size_t) { return start[1]; } static UserData expr_compound(const UserData* start, const Node*, size_t) { return start[1]; }
@ -246,4 +238,4 @@ void bind(LalrParser& parser) {
BIND(tmp); BIND(tmp);
parser.set_lexer_action_handler("string", &lalr::string_literal<IteratorType>); parser.set_lexer_action_handler("string", &lalr::string_literal<IteratorType>);
} }

View file

@ -4,7 +4,41 @@
#include <lalr/Parser.hpp> #include <lalr/Parser.hpp>
#include <lalr/string_literal.hpp> #include <lalr/string_literal.hpp>
typedef void* UserData; #include "compiler/statement.h"
#include "compiler/expression.h"
#include "Tree.hpp"
struct UserNode {
obj::BCgen::Expression* expression = nullptr;
obj::BCgen::Statement* statement = nullptr;
tp::Buffer<tp::String>* arguments = nullptr;
UserNode(obj::BCgen::Statement* stm) :
statement(stm) {}
UserNode(obj::BCgen::Expression* expr) :
expression(expr) {}
UserNode(tp::Buffer<tp::String>* argList) :
arguments(argList) {}
UserNode() = default;
obj::BCgen::Statement* releaseStm() {
auto out = statement;
statement = nullptr;
return out;
}
void destroy() {
delete statement;
delete arguments;
delete expression;
}
};
typedef UserNode UserData;
typedef char SymbolType; typedef char SymbolType;
typedef std::basic_string<SymbolType>::iterator IteratorType; typedef std::basic_string<SymbolType>::iterator IteratorType;
@ -13,4 +47,4 @@ extern const lalr::ParserStateMachine* oscript_parser_state_machine;
typedef lalr::Parser<IteratorType, UserData> LalrParser; typedef lalr::Parser<IteratorType, UserData> LalrParser;
void bind(LalrParser& parser); void bind(LalrParser& parser);

View file

@ -1,5 +1,4 @@
#include <parser/parser.h> #include <parser/parser.h>
#include "Private.hpp" #include "Private.hpp"
@ -36,7 +35,12 @@ Parser::Result Parser::parse(const tp::String& stream) {
ASSERT(parser.valid()); ASSERT(parser.valid());
parser.parse(streamStd.begin(), streamStd.end()); parser.parse(streamStd.begin(), streamStd.end());
auto scope = (BCgen::StatementScope*) parser.user_data();
return { scope, parser.accepted() && parser.full() }; BCgen::StatementScope* out = nullptr;
if (parser.accepted() && parser.full()) {
out = (BCgen::StatementScope*) parser.user_data().statement;
}
return { out, !(parser.accepted() && parser.full()) };
} }

BIN
Objects/rsc/Font.ttf Normal file

Binary file not shown.

View file

@ -42,7 +42,7 @@ if (i == 10) {
auto script = R"( auto script = R"(
var i = 10; var i = 10;
print (i + 10) * 5; print i;
)"; )";
TEST_DEF_STATIC(Complex) { TEST_DEF_STATIC(Complex) {

View file

@ -17,4 +17,18 @@ TEST_DEF_STATIC(Basic) {
delete res.scope; delete res.scope;
} }
TEST_DEF(Parser) { testBasic(); } TEST_DEF_STATIC(ErrorHandling) {
Parser parser;
String stream = "var i = true; print (i + 1) * 10; invalidCharacter ";
auto res = parser.parse(stream);
TEST(res.isError);
delete res.scope;
}
TEST_DEF(Parser) {
testBasic();
testErrorHandling();
}

View file

@ -17,22 +17,12 @@ int main() {
tp::ModuleManifest module("ObjectsTests", nullptr, nullptr, deps); tp::ModuleManifest module("ObjectsTests", nullptr, nullptr, deps);
if (module.initialize()) { if (module.initialize()) {
testParser(); testParser();
module.deinitialize(); // testCore();
} // testPrimitives();
// testInterpreter();
if (module.initialize()) {
testCore();
module.deinitialize();
}
if (module.initialize()) {
testPrimitives();
module.deinitialize();
}
if (module.initialize()) {
testInterpreter();
module.deinitialize(); module.deinitialize();
} }