fix parser issues

This commit is contained in:
2026-10-02 22:14:03 +03:00
parent 2999c295af
commit 79642d3fd1
4 changed files with 151 additions and 57 deletions
+21 -2
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <iostream> #include <iostream>
#include <sstream>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -104,7 +105,25 @@ public:
} }
} }
const char *type_str(void) std::shared_ptr<std::string> to_str(void) const
{
switch (t)
{
case VAR:
return v.s;
case CONST:
{
char buffer[128] = {0};
return std::make_shared<std::string>((std::ostringstream() << v.d).str());
}
case OPERATOR:
return std::make_shared<std::string>("OP " + std::string(op_str()));
default:
return std::make_shared<std::string>("Not a valid token!");
}
}
const char *type_str(void) const
{ {
switch (t) switch (t)
{ {
@@ -119,7 +138,7 @@ public:
} }
} }
const char *op_str(void) const char *op_str(void) const
{ {
if (t != OPERATOR) if (t != OPERATOR)
{ {
+3 -2
View File
@@ -5,7 +5,8 @@
namespace Parser { namespace Parser {
std::shared_ptr<std::vector<Expression::Token>> tokenize_input(char *input_string); std::shared_ptr<std::vector<Expression::Token>> tokenize_input(const char * const input_string);
int assert_same(std::vector<Expression::Token>& a, std::vector<Expression::Token>& b); int assert_same(const std::vector<Expression::Token>& a, const std::vector<Expression::Token>& b);
void print_token_vector(const std::vector<Expression::Token>& tv);
} }
+84 -51
View File
@@ -34,22 +34,25 @@ class Parser
} }
} }
void switch_state(enum State e) int switch_state(enum State e)
{ {
pr_debug("Leaving " << state_str(s) << ", entering " << state_str(e)); pr_debug("Leaving " << state_str(s) << ", entering " << state_str(e));
int cumulative_backtrack = 0;
switch (s) switch (s)
{ {
case I: case I:
leave_i(); cumulative_backtrack += leave_i();
break; break;
case RC: case RC:
leave_rc(); cumulative_backtrack += leave_rc();
break; break;
case RV: case RV:
leave_rv(); cumulative_backtrack += leave_rv();
break; break;
case OP: case OP:
leave_op(); cumulative_backtrack += leave_op();
break; break;
default: default:
pr_warn("Warning: broken state machine on leave"); pr_warn("Warning: broken state machine on leave");
@@ -76,6 +79,10 @@ class Parser
} }
s = e; s = e;
pr_debug("Cumulative backtrack is " << cumulative_backtrack);
return cumulative_backtrack;
} }
public: public:
@@ -121,26 +128,26 @@ public:
{ {
if (isdigit(c) || c == '.') if (isdigit(c) || c == '.')
{ {
switch_state(RC); return switch_state(RC) + 1;
return 1;
} }
else if (isalpha(c)) else if (isalpha(c))
{ {
switch_state(RV); return switch_state(RV) + 1;
return 1;
} }
else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')
{ {
switch_state(OP); return switch_state(OP) + 1;
return 1;
} }
else else
{ {
pr_warn("Unknown character skipped (" << c << "), still in idle"); pr_debug("Unknown character skipped (" << c << "), still in idle");
return 0; return 0;
} }
} }
void leave_i(void) {} int leave_i(void)
{
return 0;
}
void enter_rc(void) void enter_rc(void)
{ {
@@ -150,8 +157,7 @@ public:
{ {
if (!(isdigit(c) || c == '.')) if (!(isdigit(c) || c == '.'))
{ {
switch_state(I); return switch_state(I) + 1;
return 1;
} }
else else
{ {
@@ -159,7 +165,7 @@ public:
return 0; return 0;
} }
} }
void leave_rc(void) int leave_rc(void)
{ {
double value; double value;
@@ -171,6 +177,8 @@ public:
{ {
pv->push_back(Expression::Token(value)); pv->push_back(Expression::Token(value));
} }
return 0;
} }
void enter_rv(void) void enter_rv(void)
@@ -181,8 +189,7 @@ public:
{ {
if (!isalpha(c)) if (!isalpha(c))
{ {
switch_state(I); return switch_state(I) + 1;
return 1;
} }
else else
{ {
@@ -190,9 +197,10 @@ public:
return 0; return 0;
} }
} }
void leave_rv(void) int leave_rv(void)
{ {
pv->push_back(Expression::Token(buffer)); pv->push_back(Expression::Token(buffer));
return 0;
} }
void enter_op(void) void enter_op(void)
@@ -203,8 +211,7 @@ public:
{ {
if (!(c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')) if (!(c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')'))
{ {
switch_state(I); return switch_state(I) + 1;
return 1;
} }
else else
{ {
@@ -212,59 +219,74 @@ public:
return 0; return 0;
} }
} }
void leave_op(void) int leave_op(void)
{ {
if (!strcmp(buffer, "(")) int i, downsize;
for (i = strlen(buffer), downsize = 0; i > 0; buffer[--i] = '\0', downsize++)
{ {
pv->push_back(Expression::Token(Expression::Token::OPA)); if (!strcmp(buffer, "("))
{
pv->push_back(Expression::Token(Expression::Token::OPA));
break;
}
else if (!strcmp(buffer, ")"))
{
pv->push_back(Expression::Token(Expression::Token::CPA));
break;
}
else if (!strcmp(buffer, "+"))
{
pv->push_back(Expression::Token(Expression::Token::ADD));
break;
}
else if (!strcmp(buffer, "-"))
{
pv->push_back(Expression::Token(Expression::Token::SUB));
break;
}
else if (!strcmp(buffer, "*"))
{
pv->push_back(Expression::Token(Expression::Token::MUL));
break;
}
else if (!strcmp(buffer, "/"))
{
pv->push_back(Expression::Token(Expression::Token::DIV));
break;
}
else if (!strcmp(buffer, "**"))
{
pv->push_back(Expression::Token(Expression::Token::POW));
break;
}
} }
else if (!strcmp(buffer, ")"))
if (i)
{ {
pv->push_back(Expression::Token(Expression::Token::CPA)); return downsize;
}
else if (!strcmp(buffer, "+"))
{
pv->push_back(Expression::Token(Expression::Token::ADD));
}
else if (!strcmp(buffer, "-"))
{
pv->push_back(Expression::Token(Expression::Token::SUB));
}
else if (!strcmp(buffer, "*"))
{
pv->push_back(Expression::Token(Expression::Token::MUL));
}
else if (!strcmp(buffer, "/"))
{
pv->push_back(Expression::Token(Expression::Token::DIV));
}
else if (!strcmp(buffer, "**"))
{
pv->push_back(Expression::Token(Expression::Token::POW));
} }
else else
{ {
pr_warn("Skip unknown operator: " << buffer); pr_warn("Skip unknown operator: " << buffer);
return 0;
} }
} }
}; };
std::shared_ptr<std::vector<Expression::Token>> tokenize_input(char *input_string) std::shared_ptr<std::vector<Expression::Token>> tokenize_input(const char * const input_string)
{ {
std::shared_ptr<std::vector<Expression::Token>> pv = std::make_shared<std::vector<Expression::Token>>(); std::shared_ptr<std::vector<Expression::Token>> pv = std::make_shared<std::vector<Expression::Token>>();
Parser p(pv); Parser p(pv);
for (int i = 0, l = strlen(input_string); i < l; i++) for (int i = 0, l = strlen(input_string) + 1; i < l; i++)
{ {
i -= p.dispatch_to_current(input_string[i]); i -= p.dispatch_to_current(input_string[i]);
} }
(void) p.dispatch_to_current('\0');
return pv; return pv;
} }
int assert_same(std::vector<Expression::Token>& a, std::vector<Expression::Token>& b) int assert_same(const std::vector<Expression::Token>& a, const std::vector<Expression::Token>& b)
{ {
if (a.size() != b.size()) if (a.size() != b.size())
{ {
@@ -309,4 +331,15 @@ int assert_same(std::vector<Expression::Token>& a, std::vector<Expression::Token
return 0; return 0;
} }
void print_token_vector(const std::vector<Expression::Token>& tv)
{
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";
}
} }
+43 -2
View File
@@ -4,7 +4,9 @@
TEST(parser_proper_test_1) TEST(parser_proper_test_1)
{ {
auto o = Parser::tokenize_input((char *) "(1+2-c)"); auto o = Parser::tokenize_input("(1+2-c)");
Parser::print_token_vector(*o);
std::vector<Expression::Token> r; std::vector<Expression::Token> r;
r.push_back(Expression::Token(Expression::Token::OPA)); r.push_back(Expression::Token(Expression::Token::OPA));
@@ -22,7 +24,9 @@ TEST(parser_proper_test_1)
TEST(parser_proper_test_2) TEST(parser_proper_test_2)
{ {
auto o = Parser::tokenize_input((char *) "(1**5,-snake+marble*34*(35 / 63.2))"); auto o = Parser::tokenize_input("(1**5,-snake+marble*34*(35 / 63.2))");
Parser::print_token_vector(*o);
std::vector<Expression::Token> r; std::vector<Expression::Token> r;
r.push_back(Expression::Token(Expression::Token::OPA)); r.push_back(Expression::Token(Expression::Token::OPA));
@@ -48,8 +52,45 @@ TEST(parser_proper_test_2)
return 0; return 0;
} }
TEST(parser_proper_test_3)
{
auto o = Parser::tokenize_input(")))25.4,, 33..4 35 37 39 41 // +-*/***()()()");
Parser::print_token_vector(*o);
std::vector<Expression::Token> r;
r.push_back(Expression::Token(Expression::Token::CPA));
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));
r.push_back(Expression::Token(41));
r.push_back(Expression::Token(Expression::Token::DIV));
r.push_back(Expression::Token(Expression::Token::DIV));
r.push_back(Expression::Token(Expression::Token::ADD));
r.push_back(Expression::Token(Expression::Token::SUB));
r.push_back(Expression::Token(Expression::Token::MUL));
r.push_back(Expression::Token(Expression::Token::DIV));
r.push_back(Expression::Token(Expression::Token::POW));
r.push_back(Expression::Token(Expression::Token::MUL));
r.push_back(Expression::Token(Expression::Token::OPA));
r.push_back(Expression::Token(Expression::Token::CPA));
r.push_back(Expression::Token(Expression::Token::OPA));
r.push_back(Expression::Token(Expression::Token::CPA));
r.push_back(Expression::Token(Expression::Token::OPA));
r.push_back(Expression::Token(Expression::Token::CPA));
CHECK(Parser::assert_same(*o, r));
return 0;
}
void register_tests(void) void register_tests(void)
{ {
REGISTER(parser_proper_test_1); REGISTER(parser_proper_test_1);
REGISTER(parser_proper_test_2); REGISTER(parser_proper_test_2);
REGISTER(parser_proper_test_3);
} }