Print the AST out
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#include "lexer.hpp"
|
#include "lexer.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
using TT = Solstice::TokenType;
|
using TT = Solstice::TokenType;
|
||||||
|
|
||||||
@@ -30,36 +31,59 @@ namespace Solstice {
|
|||||||
{"/", TT::Math_Divide}
|
{"/", TT::Math_Divide}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& stream, const Literal& literal) {
|
||||||
|
switch (literal.type) {
|
||||||
|
case LiteralType::None:
|
||||||
|
stream << "<None>";
|
||||||
|
break;
|
||||||
|
case LiteralType::Bool:
|
||||||
|
stream << (*literal.getBool() ? "true" : "false");
|
||||||
|
break;
|
||||||
|
case LiteralType::Char:
|
||||||
|
stream << *literal.getChar();
|
||||||
|
break;
|
||||||
|
case LiteralType::Double:
|
||||||
|
stream << *literal.getDouble();
|
||||||
|
break;
|
||||||
|
case LiteralType::Int:
|
||||||
|
stream << *literal.getInt();
|
||||||
|
break;
|
||||||
|
case LiteralType::String:
|
||||||
|
stream << *literal.getString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::string> Literal::getString() {
|
std::optional<std::string> Literal::getString() const {
|
||||||
if (std::holds_alternative<std::string>(data)) {
|
if (std::holds_alternative<std::string>(data)) {
|
||||||
return std::get<std::string>(data);
|
return std::get<std::string>(data);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int64_t> Literal::getInt() {
|
std::optional<int64_t> Literal::getInt() const {
|
||||||
if (std::holds_alternative<int64_t>(data)) {
|
if (std::holds_alternative<int64_t>(data)) {
|
||||||
return std::get<int64_t>(data);
|
return std::get<int64_t>(data);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<double> Literal::getDouble() {
|
std::optional<double> Literal::getDouble() const {
|
||||||
if (std::holds_alternative<double>(data)) {
|
if (std::holds_alternative<double>(data)) {
|
||||||
return std::get<double>(data);
|
return std::get<double>(data);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<char> Literal::getChar() {
|
std::optional<char> Literal::getChar() const {
|
||||||
if (std::holds_alternative<char>(data)) {
|
if (std::holds_alternative<char>(data)) {
|
||||||
return std::get<char>(data);
|
return std::get<char>(data);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<bool> Literal::getBool() {
|
std::optional<bool> Literal::getBool() const {
|
||||||
if (std::holds_alternative<bool>(data)) {
|
if (std::holds_alternative<bool>(data)) {
|
||||||
return std::get<bool>(data);
|
return std::get<bool>(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,11 +66,11 @@ namespace Solstice {
|
|||||||
|
|
||||||
LiteralType type = LiteralType::None;
|
LiteralType type = LiteralType::None;
|
||||||
|
|
||||||
std::optional<std::string> getString();
|
std::optional<std::string> getString() const;
|
||||||
std::optional<int64_t> getInt();
|
std::optional<int64_t> getInt() const;
|
||||||
std::optional<double> getDouble();
|
std::optional<double> getDouble() const;
|
||||||
std::optional<char> getChar();
|
std::optional<char> getChar() const;
|
||||||
std::optional<bool> getBool();
|
std::optional<bool> getBool() const;
|
||||||
|
|
||||||
Literal(const std::string& in) : type(LiteralType::String), data(in) {}
|
Literal(const std::string& in) : type(LiteralType::String), data(in) {}
|
||||||
Literal(int64_t in) : type(LiteralType::Int), data(in) {}
|
Literal(int64_t in) : type(LiteralType::Int), data(in) {}
|
||||||
@@ -82,6 +82,8 @@ namespace Solstice {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& stream, const Literal& literal);
|
||||||
|
|
||||||
class Token {
|
class Token {
|
||||||
|
|
||||||
std::variant<Literal, std::string> data;
|
std::variant<Literal, std::string> data;
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
try {
|
try {
|
||||||
Solstice::Lexer lexer{"2 + 2"};
|
Solstice::Lexer lexer{"2 + 2 / 5"};
|
||||||
auto lexed = lexer.lex();
|
auto lexed = lexer.lex();
|
||||||
|
|
||||||
Solstice::Parser parser{lexed};
|
Solstice::Parser parser{lexed};
|
||||||
auto parsed = parser.parse();
|
auto parsed = parser.parse();
|
||||||
|
std::cout << parsed << std::endl;
|
||||||
|
|
||||||
} catch (const std::runtime_error& e) {
|
} catch (const std::runtime_error& e) {
|
||||||
std::cout << e.what() << std::endl;
|
std::cout << e.what() << std::endl;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <variant>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
using TT = Solstice::TokenType;
|
using TT = Solstice::TokenType;
|
||||||
|
|
||||||
@@ -17,6 +19,88 @@ namespace Solstice {
|
|||||||
{TT::Comparison_LesserThan, NodeType::LesserThan},
|
{TT::Comparison_LesserThan, NodeType::LesserThan},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::optional<Literal> Node::getLiteral() const {
|
||||||
|
if (std::holds_alternative<Literal>(data)) {
|
||||||
|
return std::get<Literal>(data);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::optional<std::string> Node::getIdentifier() const {
|
||||||
|
if (std::holds_alternative<std::string>(data)) {
|
||||||
|
return std::get<std::string>(data);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string nodeTypeToString(NodeType type) {
|
||||||
|
switch (type) {
|
||||||
|
case NodeType::Root:
|
||||||
|
return "Root";
|
||||||
|
case NodeType::Literal:
|
||||||
|
return "Literal";
|
||||||
|
case NodeType::Identifier:
|
||||||
|
return "Identifier";
|
||||||
|
case NodeType::FunctionBind:
|
||||||
|
return "FunctionBind";
|
||||||
|
case NodeType::Bind:
|
||||||
|
return "Bind";
|
||||||
|
case NodeType::Set:
|
||||||
|
return "Set";
|
||||||
|
case NodeType::Lambda:
|
||||||
|
return "Lambda";
|
||||||
|
case NodeType::FunctionCall:
|
||||||
|
return "FunctionCall";
|
||||||
|
case NodeType::Add:
|
||||||
|
return "Add";
|
||||||
|
case NodeType::Subtract:
|
||||||
|
return "Subtract";
|
||||||
|
case NodeType::Multiply:
|
||||||
|
return "Multiply";
|
||||||
|
case NodeType::Divide:
|
||||||
|
return "Divide";
|
||||||
|
case NodeType::Equal:
|
||||||
|
return "Equal";
|
||||||
|
case NodeType::NotEqual:
|
||||||
|
return "NotEqual";
|
||||||
|
case NodeType::GreaterThan:
|
||||||
|
return "GreaterThan";
|
||||||
|
case NodeType::LesserThan:
|
||||||
|
return "LesserThan";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& stream, const Node& node) {
|
||||||
|
stream << "Node( Type=" << nodeTypeToString(node.type);
|
||||||
|
if (node.type == NodeType::Literal) {
|
||||||
|
auto lit = node.getLiteral();
|
||||||
|
if (lit.has_value()) {
|
||||||
|
stream << ", Literal: " << *lit;
|
||||||
|
}
|
||||||
|
} else if (node.type == NodeType::Identifier) {
|
||||||
|
auto id = node.getIdentifier();
|
||||||
|
if (id.has_value()) {
|
||||||
|
stream << ", Identifier: " << *id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node.children.empty()) {
|
||||||
|
stream << ", Children: { ";
|
||||||
|
bool first = true;
|
||||||
|
for (const auto& node : node.children) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
stream << ", ";
|
||||||
|
}
|
||||||
|
stream << node;
|
||||||
|
}
|
||||||
|
stream << " }";
|
||||||
|
}
|
||||||
|
stream << " )";
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<Token> Parser::peek(int64_t ahead) {
|
std::optional<Token> Parser::peek(int64_t ahead) {
|
||||||
if (current + ahead >= input.size() || current + ahead < 0) {
|
if (current + ahead >= input.size() || current + ahead < 0) {
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
@@ -42,8 +43,13 @@ namespace Solstice {
|
|||||||
Node(NodeType type, const std::vector<Node>& children) : type(type), children(children) {}
|
Node(NodeType type, const std::vector<Node>& children) : type(type), children(children) {}
|
||||||
Node(const Literal& literal) : type(NodeType::Literal), data(literal) {}
|
Node(const Literal& literal) : type(NodeType::Literal), data(literal) {}
|
||||||
Node(const std::string& id) : type(NodeType::Identifier), data(id) {}
|
Node(const std::string& id) : type(NodeType::Identifier), data(id) {}
|
||||||
|
|
||||||
|
std::optional<Literal> getLiteral() const;
|
||||||
|
std::optional<std::string> getIdentifier() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& stream, const Node& node);
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
|
|
||||||
std::vector<Token> input;
|
std::vector<Token> input;
|
||||||
|
|||||||
Reference in New Issue
Block a user