diff --git a/config.h b/config.h index 5ae9083..c6fc99c 100644 --- a/config.h +++ b/config.h @@ -1,4 +1,6 @@ #pragma once #define DEBUG 1 +#define PRINT_DISABLE_PREFIXES 1 + #define MAX_TOKEN_STRING_LEN 256 diff --git a/inc/print.h b/inc/print.h index b8775fa..11ecc85 100644 --- a/inc/print.h +++ b/inc/print.h @@ -4,13 +4,23 @@ #include "config.h" #if DEBUG == 1 -#define pr_debug(...) std::cout << "[" << __FILE__ << ":" << __LINE__ << " " << __func__ << "] debug: " << __VA_ARGS__ << "\n" -#define pri_debug(...) std::cout << __VA_ARGS__ -#define prs_debug(...) std::cout << "[" << __FILE__ << ":" << __LINE__ << " " << __func__ << "] debug: " << __VA_ARGS__ + #if PRINT_DISABLE_PREFIXES == 1 + #define pr_debug(...) std::cout << "debug: " << __VA_ARGS__ << "\n" + #define pri_debug(...) std::cout << __VA_ARGS__ + #define prs_debug(...) std::cout << "debug: " << __VA_ARGS__ + #else + #define pr_debug(...) std::cout << "[" << __FILE__ << ":" << __LINE__ << " " << __func__ << "] debug: " << __VA_ARGS__ << "\n" + #define pri_debug(...) std::cout << __VA_ARGS__ + #define prs_debug(...) std::cout << "[" << __FILE__ << ":" << __LINE__ << " " << __func__ << "] debug: " << __VA_ARGS__ + #endif #else #define pr_debug(...) do {} while (0) #define pri_debug(...) do {} while (0) #define prs_debug(...) do {} while (0) #endif +#if PRINT_DISABLE_PREFIXES == 1 +#define pr_warn(...) std::cout << "warning: " << __VA_ARGS__ << "\n" +#else #define pr_warn(...) std::cout << "[" << __FILE__ << ":" << __LINE__ << " " << __func__ << "] warning: " << __VA_ARGS__ << "\n" +#endif diff --git a/inc/syntaxer.hpp b/inc/syntaxer.hpp index 4d108aa..a40efed 100644 --- a/inc/syntaxer.hpp +++ b/inc/syntaxer.hpp @@ -6,12 +6,7 @@ namespace Syntax { -struct SyntaxIssue -{ - -}; - -std::vector check_syntax(std::vector& tv); +int check_syntax(std::vector& tv); void apply_corrections(std::vector& tv); std::vector build_op_vector(const std::vector& tv); diff --git a/src/main.cpp b/src/main.cpp index e31310a..d9ea05d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,13 @@ int main(int argc, char **argv) } std::vector tv = Parser::tokenize_input(argv[1]); + + if (Syntax::check_syntax(tv)) + { + return 0; + } + Syntax::apply_corrections(tv); + std::vector ov = Syntax::build_op_vector(tv); } diff --git a/src/syntaxer.cpp b/src/syntaxer.cpp index 61c7714..5fcffa0 100644 --- a/src/syntaxer.cpp +++ b/src/syntaxer.cpp @@ -1,18 +1,215 @@ -#include "syntaxer.hpp" -#include "parser.hpp" #include "expression.hpp" -#include +#include "parser.hpp" #include "print.h" +#include "syntaxer.hpp" +#include +#include namespace Syntax { -#if 0 -std::vector check_syntax(std::vector& tv); +static void highlight_issue(const std::vector& tv, const int location) { + int start = location - 7 < 0 ? 0 : location - 7; + int finish = location + 7 > tv.size() - 1 ? tv.size() - 1 : location + 7; + std::cout << " >>> "; + + for (int i = start; i <= finish; i++) + { + if (i == location) + { + std::cout << "\033[31m" << *tv[i].to_math_str() << "\033[0m "; + } + else + { + std::cout << *tv[i].to_math_str() << " "; + } + } + + std::cout << "\n"; } -#endif +int check_syntax(std::vector& tv) +{ + int problem_cnt = 0; + + // check token type sequence + { + for (int i = 0, l = tv.size() - 1, pc; pc = problem_cnt, i < l; i++) + { + switch (tv[i].t) + { + case Expression::Token::VAR: + case Expression::Token::CONST: + switch (tv[i+1].t) + { + case Expression::Token::OPERATOR: + switch (tv[i+1].v.o) + { + case Expression::Token::OPA: + pr_warn("Expected operator at token " << i << ", got opening bracket"); + problem_cnt++; + break; + case Expression::Token::CPA: + break; + default: + break; + } + break; + case Expression::Token::VAR: + pr_warn("Expected operator at token " << i << ", got variable"); + problem_cnt++; + break; + case Expression::Token::CONST: + pr_warn("Expected operator at token " << i << ", got constant"); + problem_cnt++; + break; + default: + pr_warn("Impossible token type, this is a bug!"); + break; + } + break; + case Expression::Token::OPERATOR: + switch (tv[i].v.o) + { + case Expression::Token::OPA: + switch (tv[i+1].t) + { + case Expression::Token::OPERATOR: + switch (tv[i+1].v.o) + { + case Expression::Token::OPA: + break; + case Expression::Token::CPA: + pr_warn("Expected value at token " << i << ", got closing bracket"); + problem_cnt++; + break; + default: + pr_warn("Expected value at token " << i << ", got operator"); + problem_cnt++; + break; + } + break; + case Expression::Token::CONST: + case Expression::Token::VAR: + break; + default: + pr_warn("Impossible token type, this is a bug!"); + break; + } + break; + case Expression::Token::CPA: + switch (tv[i+1].t) + { + case Expression::Token::OPERATOR: + switch (tv[i+1].v.o) + { + case Expression::Token::CPA: + break; + case Expression::Token::OPA: + pr_warn("Expected operator at token " << i << ", got opening bracket"); + problem_cnt++; + break; + default: + break; + } + break; + case Expression::Token::CONST: + pr_warn("Expected operator at token " << i << ", got constant"); + problem_cnt++; + break; + case Expression::Token::VAR: + pr_warn("Expected operator at token " << i << ", got variable"); + problem_cnt++; + break; + default: + pr_warn("Impossible token type, this is a bug!"); + break; + } + break; + default: + switch (tv[i+1].t) + { + case Expression::Token::OPERATOR: + switch (tv[i+1].v.o) + { + case Expression::Token::CPA: + pr_warn("Expected value at token " << i << ", got closing bracket"); + problem_cnt++; + break; + case Expression::Token::OPA: + break; + default: + pr_warn("Expected value at token " << i << ", got operator"); + problem_cnt++; + break; + } + break; + case Expression::Token::CONST: + break; + case Expression::Token::VAR: + break; + default: + pr_warn("Impossible token type, this is a bug!"); + break; + } + break; + } + break; + default: + pr_warn("Impossible token type, this is a bug!"); + break; + } + + if (pc != problem_cnt) + { + highlight_issue(tv, i + 1); + } + } + } + + // check bracket matching + { + std::stack s; + + for (int i = 0, l = tv.size(); i < l; i++) + { + if (tv[i].t == Expression::Token::OPERATOR) + { + switch (tv[i].v.o) + { + case Expression::Token::OPA: + s.push(i); + break; + case Expression::Token::CPA: + if (s.size()) + { + s.pop(); + } + else + { + pr_warn("Missing opening bracket at token " << i); + problem_cnt++; + highlight_issue(tv, i); + } + break; + default: + break; + } + } + } + + for (int i = 0, l = s.size(); i < l; i++) + { + problem_cnt++; + pr_warn("Opening bracket at token " << s.top() << " expected a closing bracket, but none found"); + highlight_issue(tv, s.top()); + s.pop(); + } + } + + return problem_cnt; +} // get mop = Math OPerator location (=absolute index in std::vector) // mapper of 'priority vector index' -> 'token vector index' @@ -377,6 +574,11 @@ void apply_corrections(std::vector& tv) std::vector mp; create_prios_vector(tv, mp); + if (mp.size() == 0) + { + return; + } + for (int current_prio_level = mp[get_max_index(mp)]; current_prio_level >= 0; current_prio_level--) { // calculate how many ranges need to be processed at this level