update with initial syntaxer implementation
This commit is contained in:
+8
-2
@@ -11,15 +11,20 @@ set (GLOBAL_INC PRIVATE
|
|||||||
|
|
||||||
|
|
||||||
add_library(parser STATIC)
|
add_library(parser STATIC)
|
||||||
|
|
||||||
target_sources(parser PRIVATE
|
target_sources(parser PRIVATE
|
||||||
src/parser.cpp
|
src/parser.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(parser PRIVATE
|
target_include_directories(parser PRIVATE
|
||||||
${GLOBAL_INC}
|
${GLOBAL_INC}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_library(syntaxer STATIC)
|
||||||
|
target_sources(syntaxer PRIVATE
|
||||||
|
src/syntaxer.cpp
|
||||||
|
)
|
||||||
|
target_include_directories(syntaxer PRIVATE
|
||||||
|
${GLOBAL_INC}
|
||||||
|
)
|
||||||
|
|
||||||
add_executable(tester)
|
add_executable(tester)
|
||||||
|
|
||||||
@@ -34,4 +39,5 @@ target_include_directories(tester PRIVATE
|
|||||||
|
|
||||||
target_link_libraries(tester PRIVATE
|
target_link_libraries(tester PRIVATE
|
||||||
parser
|
parser
|
||||||
|
syntaxer
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
|
#define MAX_TOKEN_STRING_LEN 256
|
||||||
|
|||||||
+22
-3
@@ -66,6 +66,11 @@ public:
|
|||||||
}
|
}
|
||||||
} v;
|
} v;
|
||||||
|
|
||||||
|
Token(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Token(std::string s)
|
Token(std::string s)
|
||||||
: v(s)
|
: v(s)
|
||||||
{
|
{
|
||||||
@@ -168,9 +173,23 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class TreeNode {
|
class TreeNode {
|
||||||
std::shared_ptr<Token> l; // left hand
|
public:
|
||||||
std::shared_ptr<Token> o; // operation
|
TreeNode *l; // left hand
|
||||||
std::shared_ptr<Token> r; // right hand
|
TreeNode *r; // right hand
|
||||||
|
Token o; // operator
|
||||||
|
|
||||||
|
~TreeNode()
|
||||||
|
{
|
||||||
|
if (l != nullptr)
|
||||||
|
{
|
||||||
|
delete l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != nullptr)
|
||||||
|
{
|
||||||
|
delete r;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,4 +9,4 @@
|
|||||||
#define pr_debug(...) do {} while (0)
|
#define pr_debug(...) do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define pr_warn(...) std::cout << "[" << __func__ << ":" << __LINE__ << "] warning: " << __VA_ARGS__ << "\n"
|
#define pr_warn(...) std::cout << "[" << __FILE__ << ":" << __LINE__ << " " << __func__ << "] warning: " << __VA_ARGS__ << "\n"
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include "expression.hpp"
|
||||||
|
|
||||||
|
namespace Syntax
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SyntaxIssue
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<SyntaxIssue> check_syntax(std::vector<Expression::Token>& tv);
|
||||||
|
std::shared_ptr<Expression::TreeNode> build_op_tree(std::vector<Expression::Token>& tv);
|
||||||
|
|
||||||
|
}
|
||||||
+49
-3
@@ -97,12 +97,14 @@ public:
|
|||||||
|
|
||||||
void buf_clear(void)
|
void buf_clear(void)
|
||||||
{
|
{
|
||||||
memset(buffer, 0, 256);
|
memset(buffer, 0, MAX_TOKEN_STRING_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void buf_push(char c)
|
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)
|
int dispatch_to_current(char c)
|
||||||
@@ -140,7 +142,12 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,6 +174,34 @@ public:
|
|||||||
}
|
}
|
||||||
int leave_rc(void)
|
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;
|
double value;
|
||||||
|
|
||||||
if (!sscanf(buffer, "%lf", &value))
|
if (!sscanf(buffer, "%lf", &value))
|
||||||
@@ -342,4 +377,15 @@ void print_token_vector(const std::vector<Expression::Token>& tv)
|
|||||||
std::cout << "(" << *tv[i].to_str() << ")\n";
|
std::cout << "(" << *tv[i].to_str() << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_token_vector(const std::vector<Expression::Token>& tv, const std::vector<unsigned char>& 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";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
#include "syntaxer.hpp"
|
||||||
|
#include "expression.hpp"
|
||||||
|
#include <vector>
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
namespace Syntax {
|
||||||
|
|
||||||
|
struct OpImportance
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
int prio;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
std::vector<SyntaxIssue> check_syntax(std::vector<Expression::Token>& tv);
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::shared_ptr<Expression::TreeNode> build_op_tree(const std::vector<Expression::Token>& 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<Expression::Token> mv = tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build operation tree
|
||||||
|
|
||||||
|
Expression::TreeNode *root = new Expression::TreeNode;
|
||||||
|
|
||||||
|
return std::shared_ptr<Expression::TreeNode>(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+11
-1
@@ -1,5 +1,6 @@
|
|||||||
#include "test-tools.hpp"
|
#include "test-tools.hpp"
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
|
#include "syntaxer.hpp"
|
||||||
#include "expression.hpp"
|
#include "expression.hpp"
|
||||||
|
|
||||||
TEST(parser_proper_test_1)
|
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(Expression::Token::CPA));
|
r.push_back(Expression::Token(Expression::Token::CPA));
|
||||||
r.push_back(Expression::Token(25.4));
|
r.push_back(Expression::Token(25.4));
|
||||||
r.push_back(Expression::Token(33));
|
|
||||||
r.push_back(Expression::Token(35));
|
r.push_back(Expression::Token(35));
|
||||||
r.push_back(Expression::Token(37));
|
r.push_back(Expression::Token(37));
|
||||||
r.push_back(Expression::Token(39));
|
r.push_back(Expression::Token(39));
|
||||||
@@ -88,9 +88,19 @@ TEST(parser_proper_test_3)
|
|||||||
return 0;
|
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)
|
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);
|
REGISTER(parser_proper_test_3);
|
||||||
|
|
||||||
|
REGISTER(tree_proper_test_1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user