Basic expression parsing

This commit is contained in:
Rafał Grodziński
2025-05-30 13:33:45 +09:00
parent d5d21aa422
commit 1aceef1273
7 changed files with 197 additions and 35 deletions

View File

@@ -1,14 +1,95 @@
#include "Expression.h" #include "Expression.h"
ExpressionInvalid Expression::Invalid = ExpressionInvalid(); std::shared_ptr<Expression> Expression::Invalid = std::make_shared<Expression>(Expression::Kind::INVALID, Token::Invalid, nullptr, nullptr);
std::string ExpressionInvalid::toString() { Expression::Expression(Kind kind, Token token, shared_ptr<Expression> left, shared_ptr<Expression> right) {
return "Invalid"; switch (kind) {
case LITERAL:
setupLiteral(token);
break;
case BINARY:
setupBinary(token, left, right);
break;
case INVALID:
break;
}
} }
/*ExpressionInteger::ExpressionInteger(Token token) { void Expression::setupLiteral(Token token) {
bool isKindValid = token.isOneOf({Token::Kind::INTEGER});
if (!isKindValid)
return;
kind = LITERAL;
integer = stoi(token.getLexme());
} }
std::string ExpressionInteger::toString() { void Expression::setupBinary(Token token, shared_ptr<Expression> left, shared_ptr<Expression> right) {
return "INTEGER"; bool isKindValid = token.isOneOf({Token::Kind::PLUS, Token::Kind::MINUS, Token::Kind::STAR, Token::Kind::SLASH, Token::Kind::PERCENT});
}*/ bool isLeftValid = left != nullptr && left->getKind() != Kind::INVALID;
bool isRightValid = right != nullptr && right->getKind() != Kind::INVALID;
if (!isKindValid || !isLeftValid || !isRightValid)
return;
kind = BINARY;
switch (token.getKind()) {
case Token::Kind::PLUS:
operation = ADD;
break;
case Token::Kind::MINUS:
operation = SUB;
break;
case Token::Kind::STAR:
operation = MUL;
break;
case Token::Kind::SLASH:
operation = DIV;
break;
case Token::Kind::PERCENT:
operation = MOD;
break;
case Token::Kind::INVALID:
break;
}
this->left = left;
this->right = right;
}
Expression::Kind Expression::getKind() {
return kind;
}
bool Expression::operator==(Expression const& other) {
return kind == other.kind;
}
bool Expression::operator!=(Expression const& other) {
return kind != other.kind;
}
std::string Expression::toString() {
switch (kind) {
case LITERAL:
return to_string(integer);
case BINARY:
switch (operation) {
case ADD:
return "<+ " + left->toString() + " " + right->toString() + ">";
case SUB:
return "<- " + left->toString() + " " + right->toString() + ">";
case MUL:
return "<* " + left->toString() + " " + right->toString() + ">";
case DIV:
return "</ " + left->toString() + " " + right->toString() + ">";
case MOD:
return "<% " + left->toString() + " " + right->toString() + ">";
case NONE:
return "NONE";
}
case INVALID:
return "INVALID";
}
}

View File

@@ -3,23 +3,43 @@
#include "Token.h" #include "Token.h"
class ExpressionInvalid; using namespace std;
class Expression { class Expression {
public: public:
static ExpressionInvalid Invalid; enum Kind {
LITERAL,
BINARY,
INVALID
};
virtual std::string toString() = 0; enum Operation {
}; ADD,
SUB,
MUL,
DIV,
MOD,
NONE
};
class ExpressionInvalid { private:
Kind kind = INVALID;
int64_t integer = 0;
Operation operation = NONE;
shared_ptr<Expression> left = nullptr;
shared_ptr<Expression> right = nullptr;
}; void setupLiteral(Token token);
void setupBinary(Token token, shared_ptr<Expression> left, shared_ptr<Expression> right);
/*class ExpressionInteger: Expression {
public: public:
ExpressionInteger(Token token); Expression(Kind kind, Token token, shared_ptr<Expression> left, shared_ptr<Expression> right);
std::string toString() override; Kind getKind();
};*/ bool operator==(Expression const& other);
bool operator!=(Expression const& other);
string toString();
static shared_ptr<Expression> Invalid;
};
#endif #endif

View File

@@ -1,24 +1,61 @@
#include "Parser.h" #include "Parser.h"
Parser::Parser(std::vector<Token> tokens) : tokens(tokens) { Parser::Parser(vector<Token> tokens): tokens(tokens) {
} }
/*Expression Parser::getExpression() { shared_ptr<Expression> Parser::getExpression() {
return term(); return term();
}*/ }
/*Expression Parser::term() { shared_ptr<Expression> Parser::term() {
shared_ptr<Expression> expression = factor();
}*/ while (tokens.at(currentIndex).isOneOf({Token::Kind::PLUS, Token::Kind::MINUS})) {
expression = matchBinary(expression);
}
/*Expression Parser::primary() { return expression;
}
}*/ shared_ptr<Expression> Parser::factor() {
shared_ptr<Expression> expression = primary();
Expression Parser::matchInteger() { while (tokens.at(currentIndex).isOneOf({Token::Kind::STAR, Token::Kind::SLASH, Token::Kind::PERCENT})) {
//Token token = tokens.at(currentIndex); expression = matchBinary(expression);
//if (token.getKind() == Token::Kind::INTEGER) }
// ExpressionInteger(token);
return expression;
}
shared_ptr<Expression> Parser::primary() {
shared_ptr<Expression> expression = Expression::Invalid;
do {
if((expression = matchInteger()) != Expression::Invalid)
break;
} while(false);
return expression;
}
shared_ptr<Expression> Parser::matchInteger() {
Token token = tokens.at(currentIndex);
if (token.getKind() == Token::Kind::INTEGER) {
currentIndex++;
return make_shared<Expression>(Expression::Kind::LITERAL, token, nullptr, nullptr);
}
return Expression::Invalid;
}
shared_ptr<Expression> Parser::matchBinary(shared_ptr<Expression> left) {
Token token = tokens.at(currentIndex);
if (token.isOneOf({Token::Kind::PLUS, Token::Kind::MINUS, Token::Kind::STAR, Token::Kind::SLASH, Token::Kind::PERCENT})) {
currentIndex++;
shared_ptr<Expression> right = factor();
return make_shared<Expression>(Expression::Kind::BINARY, token, left, right);
}
return Expression::Invalid; return Expression::Invalid;
} }

View File

@@ -5,19 +5,23 @@
#include "Token.h" #include "Token.h"
#include "Expression.h" #include "Expression.h"
using namespace std;
class Parser { class Parser {
private: private:
std::vector<Token> tokens; vector<Token> tokens;
int currentIndex = 0; int currentIndex = 0;
//Expression term(); shared_ptr<Expression> term(); // +, -
//Expression primary(); shared_ptr<Expression> factor(); // *, /, %
shared_ptr<Expression> primary();
Expression matchInteger(); shared_ptr<Expression> matchInteger();
shared_ptr<Expression> matchBinary(shared_ptr<Expression> left);
public: public:
Parser(std::vector<Token> tokens); Parser(vector<Token> tokens);
//Expression getExpression(); shared_ptr<Expression> getExpression();
}; };
#endif #endif

View File

@@ -21,6 +21,15 @@ bool Token::operator!=(Token const& other) {
return kind != other.kind; return kind != other.kind;
} }
bool Token::isOneOf(std::vector<Kind> kinds) {
for (Kind &kind : kinds) {
if (kind == this->kind)
return true;
}
return false;
}
std::string Token::toString() { std::string Token::toString() {
switch (kind) { switch (kind) {
case PLUS: case PLUS:

View File

@@ -35,6 +35,7 @@ public:
std::string getLexme(); std::string getLexme();
bool operator==(Token const& other); bool operator==(Token const& other);
bool operator!=(Token const& other); bool operator!=(Token const& other);
bool isOneOf(std::vector<Kind> kinds);
std::string toString(); std::string toString();
static Token Invalid; static Token Invalid;

View File

@@ -1,7 +1,13 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "Lexer.h"
#include "Token.h" #include "Token.h"
#include "Lexer.h"
#include "Expression.h"
#include "Parser.h"
using namespace std;
std::string readFile(std::string fileName) { std::string readFile(std::string fileName) {
std::ifstream file(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate); std::ifstream file(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
@@ -30,5 +36,9 @@ int main(int argc, char **argv) {
std::cout << token.toString() << " "; std::cout << token.toString() << " ";
std::cout << std::endl; std::cout << std::endl;
Parser parser(tokens);
shared_ptr<Expression> expression = parser.getExpression();
cout << expression->toString() << endl;
return 0; return 0;
} }