From f00ed50d329970ad8f1f0549b950b8deef610003 Mon Sep 17 00:00:00 2001 From: hasslesstech Date: Sun, 4 Oct 2026 14:13:14 +0300 Subject: [PATCH] update with initial syntaxer implementation --- CMakeLists.txt | 10 ++++-- config.h | 1 + inc/expression.hpp | 25 +++++++++++++-- inc/print.h | 2 +- inc/syntaxer.hpp | 18 +++++++++++ src/parser.cpp | 52 +++++++++++++++++++++++++++++-- src/syntaxer.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++ src/test-cases.cpp | 12 ++++++- 8 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 inc/syntaxer.hpp create mode 100644 src/syntaxer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d378480..6dab1a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,15 +11,20 @@ set (GLOBAL_INC PRIVATE add_library(parser STATIC) - target_sources(parser PRIVATE src/parser.cpp ) - target_include_directories(parser PRIVATE ${GLOBAL_INC} ) +add_library(syntaxer STATIC) +target_sources(syntaxer PRIVATE + src/syntaxer.cpp +) +target_include_directories(syntaxer PRIVATE + ${GLOBAL_INC} +) add_executable(tester) @@ -34,4 +39,5 @@ target_include_directories(tester PRIVATE target_link_libraries(tester PRIVATE parser + syntaxer ) diff --git a/config.h b/config.h index 30759e6..5ae9083 100644 --- a/config.h +++ b/config.h @@ -1,3 +1,4 @@ #pragma once #define DEBUG 1 +#define MAX_TOKEN_STRING_LEN 256 diff --git a/inc/expression.hpp b/inc/expression.hpp index 4c8a051..a3dcbd7 100644 --- a/inc/expression.hpp +++ b/inc/expression.hpp @@ -66,6 +66,11 @@ public: } } v; + Token(void) + { + + } + Token(std::string s) : v(s) { @@ -168,9 +173,23 @@ public: }; class TreeNode { - std::shared_ptr l; // left hand - std::shared_ptr o; // operation - std::shared_ptr r; // right hand +public: + TreeNode *l; // left hand + TreeNode *r; // right hand + Token o; // operator + + ~TreeNode() + { + if (l != nullptr) + { + delete l; + } + + if (r != nullptr) + { + delete r; + } + } }; } diff --git a/inc/print.h b/inc/print.h index 95725d8..91b430e 100644 --- a/inc/print.h +++ b/inc/print.h @@ -9,4 +9,4 @@ #define pr_debug(...) do {} while (0) #endif -#define pr_warn(...) std::cout << "[" << __func__ << ":" << __LINE__ << "] warning: " << __VA_ARGS__ << "\n" +#define pr_warn(...) std::cout << "[" << __FILE__ << ":" << __LINE__ << " " << __func__ << "] warning: " << __VA_ARGS__ << "\n" diff --git a/inc/syntaxer.hpp b/inc/syntaxer.hpp new file mode 100644 index 0000000..2c85d76 --- /dev/null +++ b/inc/syntaxer.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include "expression.hpp" + +namespace Syntax +{ + +struct SyntaxIssue +{ + +}; + +std::vector check_syntax(std::vector& tv); +std::shared_ptr build_op_tree(std::vector& tv); + +} diff --git a/src/parser.cpp b/src/parser.cpp index 4d08afb..e43f227 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -97,12 +97,14 @@ public: void buf_clear(void) { - memset(buffer, 0, 256); + memset(buffer, 0, MAX_TOKEN_STRING_LEN); } void buf_push(char c) { - buffer[strlen(buffer)] = c; + if (int i = strlen(buffer); i < MAX_TOKEN_STRING_LEN - 1) { + buffer[i] = c; + } } int dispatch_to_current(char c) @@ -140,7 +142,12 @@ public: } else { - pr_debug("Unknown character skipped (" << c << "), still in idle"); + // as per requirements (report all wrong symbols) + if (c != ' ' && c != '\0') + { + pr_warn("Unrecognized character: " << c); + } + return 0; } } @@ -167,6 +174,34 @@ public: } int leave_rc(void) { + // additional check as per requirements + { + int i, c; +#if (MAX_TOKEN_STRING_LEN % 8) == 0 + for (i = 0, c = 0; i < MAX_TOKEN_STRING_LEN; i += 8) + { + c += (buffer[i+0] == '.') + + (buffer[i+1] == '.') + + (buffer[i+2] == '.') + + (buffer[i+3] == '.') + + (buffer[i+4] == '.') + + (buffer[i+5] == '.') + + (buffer[i+6] == '.') + + (buffer[i+7] == '.'); + } +#else + for (int i = 0, c = 0; i < MAX_TOKEN_STRING_LEN; i++) + { + c += buffer[i] == '.'; + } +#endif + if (c > 1) + { + pr_warn("Too many dots in CONST: " << buffer); + return 0; + } + } + double value; if (!sscanf(buffer, "%lf", &value)) @@ -342,4 +377,15 @@ void print_token_vector(const std::vector& tv) std::cout << "(" << *tv[i].to_str() << ")\n"; } +void print_token_vector(const std::vector& tv, const std::vector& colorcoding) +{ + int i, l; + for (i = 0, l = tv.size() - 1; i < l; i++) + { + std::cout << "(" << *tv[i].to_str() << ") "; + } + + std::cout << "(" << *tv[i].to_str() << ")\n"; +} + } diff --git a/src/syntaxer.cpp b/src/syntaxer.cpp new file mode 100644 index 0000000..2aefe48 --- /dev/null +++ b/src/syntaxer.cpp @@ -0,0 +1,78 @@ +#include "syntaxer.hpp" +#include "expression.hpp" +#include +#include "print.h" + +namespace Syntax { + +struct OpImportance +{ + int pos; + int prio; +}; + +#if 0 +std::vector check_syntax(std::vector& tv); +{ + +} +#endif + +std::shared_ptr build_op_tree(const std::vector& tv) +{ + // define operator precedency + int prios_cnt = ({ + int i = 0, c = 0, l = tv.size(); + for (; i < l; c += tv[i].t == Expression::Token::OPERATOR + && tv[i].v.o != Expression::Token::CPA + && tv[i].v.o != Expression::Token::OPA, i++); + c; + }); + OpImportance prios[prios_cnt]; + + for (int i = 0, p = 0, cp = 0, l = tv.size(); i < l; i++) + { + if (tv[i].t == Expression::Token::OPERATOR) + { + switch (tv[i].v.o) + { + case Expression::Token::OPA: + cp++; + break; + case Expression::Token::CPA: + cp--; + break; + case Expression::Token::ADD: + case Expression::Token::SUB: + case Expression::Token::MUL: + case Expression::Token::DIV: + case Expression::Token::POW: + prios[p].prio = cp; + prios[p].pos = i; + p++; + break; + default: + pr_warn("Token vector has broken operator at " << i); + break; + } + } + } + + for (int i = 0; i < prios_cnt; i++) + { + pr_debug("pos=" << prios[i].pos << ",prio=" << prios[i].prio); + } + + // build dependency graph + { + std::vector mv = tv; + } + + // build operation tree + + Expression::TreeNode *root = new Expression::TreeNode; + + return std::shared_ptr(root); +} + +} diff --git a/src/test-cases.cpp b/src/test-cases.cpp index eb365c4..d902f36 100644 --- a/src/test-cases.cpp +++ b/src/test-cases.cpp @@ -1,5 +1,6 @@ #include "test-tools.hpp" #include "parser.hpp" +#include "syntaxer.hpp" #include "expression.hpp" TEST(parser_proper_test_1) @@ -63,7 +64,6 @@ TEST(parser_proper_test_3) r.push_back(Expression::Token(Expression::Token::CPA)); r.push_back(Expression::Token(Expression::Token::CPA)); r.push_back(Expression::Token(25.4)); - r.push_back(Expression::Token(33)); r.push_back(Expression::Token(35)); r.push_back(Expression::Token(37)); r.push_back(Expression::Token(39)); @@ -88,9 +88,19 @@ TEST(parser_proper_test_3) return 0; } +TEST(tree_proper_test_1) +{ + auto o = Parser::tokenize_input("(1**5 * (1 + 2 + 3 + 4))"); + Syntax::build_op_tree(*o); + + return 0; +} + void register_tests(void) { REGISTER(parser_proper_test_1); REGISTER(parser_proper_test_2); REGISTER(parser_proper_test_3); + + REGISTER(tree_proper_test_1); }