Basic list support
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
class Lexer {
|
class Lexer {
|
||||||
private:
|
private:
|
||||||
std::vector<char> delimiters = {
|
std::vector<char> delimiters = {
|
||||||
'(', ')', '{', '}', '.', '\n', ' '
|
'(', ')', '{', '}', '[', ']', '.', '\n', ' ', ','
|
||||||
};
|
};
|
||||||
std::string file;
|
std::string file;
|
||||||
size_t incrementor = -1;
|
size_t incrementor = -1;
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ ASTValue::ASTValue(std::string in) : type(ValueType::String), value(in) {}
|
|||||||
ASTValue::ASTValue(bool in) : type(ValueType::Bool), value(in) {}
|
ASTValue::ASTValue(bool in) : type(ValueType::Bool), value(in) {}
|
||||||
ASTValue::ASTValue(long long in) : type(ValueType::Int), value(in) {}
|
ASTValue::ASTValue(long long in) : type(ValueType::Int), value(in) {}
|
||||||
ASTValue::ASTValue(double in) : type(ValueType::Float), value(in) {}
|
ASTValue::ASTValue(double in) : type(ValueType::Float), value(in) {}
|
||||||
|
ASTValue::ASTValue(ASTList in) : type(ValueType::List), value(std::move(in)) {}
|
||||||
|
|
||||||
|
ASTList::ASTList(std::vector<ASTNode> in) : elements(std::move(in)) {}
|
||||||
|
|
||||||
ValueType ASTValue::getValueType(std::string in) {
|
ValueType ASTValue::getValueType(std::string in) {
|
||||||
if (in.size() < 1) {
|
if (in.size() < 1) {
|
||||||
@@ -55,7 +58,7 @@ ASTFunctionCall::ASTFunctionCall(std::string func, std::vector<ASTNode> args) :
|
|||||||
ASTIdentifier::ASTIdentifier(std::string in) : name(std::move(in)) {}
|
ASTIdentifier::ASTIdentifier(std::string in) : name(std::move(in)) {}
|
||||||
|
|
||||||
|
|
||||||
std::optional<std::string> ASTValue::getString() {
|
std::optional<std::string> ASTValue::getString() const {
|
||||||
if (type == ValueType::String && std::holds_alternative<std::string>(value)) {
|
if (type == ValueType::String && std::holds_alternative<std::string>(value)) {
|
||||||
return std::get<std::string>(value);
|
return std::get<std::string>(value);
|
||||||
} else {
|
} else {
|
||||||
@@ -63,7 +66,7 @@ std::optional<std::string> ASTValue::getString() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int> ASTValue::getInt() {
|
std::optional<int> ASTValue::getInt() const {
|
||||||
if (type == ValueType::Int && std::holds_alternative<long long>(value)) {
|
if (type == ValueType::Int && std::holds_alternative<long long>(value)) {
|
||||||
return std::get<long long>(value);
|
return std::get<long long>(value);
|
||||||
} else {
|
} else {
|
||||||
@@ -71,7 +74,7 @@ std::optional<int> ASTValue::getInt() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<double> ASTValue::getFloat() {
|
std::optional<double> ASTValue::getFloat() const {
|
||||||
if (type == ValueType::Float && std::holds_alternative<double>(value)) {
|
if (type == ValueType::Float && std::holds_alternative<double>(value)) {
|
||||||
return std::get<double>(value);
|
return std::get<double>(value);
|
||||||
} else {
|
} else {
|
||||||
@@ -79,7 +82,7 @@ std::optional<double> ASTValue::getFloat() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<bool> ASTValue::getBool() {
|
std::optional<bool> ASTValue::getBool() const {
|
||||||
if (type == ValueType::Bool && std::holds_alternative<bool>(value)) {
|
if (type == ValueType::Bool && std::holds_alternative<bool>(value)) {
|
||||||
return std::get<bool>(value);
|
return std::get<bool>(value);
|
||||||
} else {
|
} else {
|
||||||
@@ -87,6 +90,18 @@ std::optional<bool> ASTValue::getBool() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<ASTList> ASTValue::getList() const {
|
||||||
|
if (type == ValueType::List && std::holds_alternative<ASTList>(value)) {
|
||||||
|
return std::get<ASTList>(value);
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ASTNode> ASTList::getElements() const {
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::string> ASTCodeBlock::consume() {
|
std::optional<std::string> ASTCodeBlock::consume() {
|
||||||
if (iterator < content.size()) {
|
if (iterator < content.size()) {
|
||||||
return content[iterator++]; // Post-increment: returns current, then increments
|
return content[iterator++]; // Post-increment: returns current, then increments
|
||||||
@@ -132,6 +147,12 @@ TokenType ASTCodeBlock::getTokenType() {
|
|||||||
if (token == ")") {
|
if (token == ")") {
|
||||||
return TokenType::CloseParen;
|
return TokenType::CloseParen;
|
||||||
}
|
}
|
||||||
|
if (token == "[") {
|
||||||
|
return TokenType::ListStart;
|
||||||
|
}
|
||||||
|
if (token == "]") {
|
||||||
|
return TokenType::ListEnd;
|
||||||
|
}
|
||||||
if (token == "\n") {
|
if (token == "\n") {
|
||||||
return TokenType::NewLine;
|
return TokenType::NewLine;
|
||||||
}
|
}
|
||||||
@@ -288,6 +309,40 @@ void ASTCodeBlock::parseBlock() {
|
|||||||
nodes.emplace_back(std::make_shared<ASTCodeBlock>(body));
|
nodes.emplace_back(std::make_shared<ASTCodeBlock>(body));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TokenType::ListStart: {
|
||||||
|
std::vector<std::string> body;
|
||||||
|
int depth = 1;
|
||||||
|
while (depth > 0) {
|
||||||
|
std::optional<std::string> token = consume();
|
||||||
|
if (token.has_value()) {
|
||||||
|
if (token.value() == "[") {
|
||||||
|
depth++;
|
||||||
|
} else if (token.value() == "]") {
|
||||||
|
depth--;
|
||||||
|
if (depth == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body.push_back(token.value());
|
||||||
|
} else {
|
||||||
|
std::cout << "Reached end of file while parsing list" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASTCodeBlock list_elements_block(body);
|
||||||
|
std::vector<ASTNode> final_nodes;
|
||||||
|
for (const auto& node : list_elements_block.nodes) {
|
||||||
|
if (std::holds_alternative<std::shared_ptr<ASTIdentifier>>(node)) {
|
||||||
|
auto ident = std::get<std::shared_ptr<ASTIdentifier>>(node);
|
||||||
|
if (ident->name == ",") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final_nodes.push_back(node);
|
||||||
|
}
|
||||||
|
nodes.emplace_back(std::make_shared<ASTValue>(ASTList(final_nodes)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -297,7 +352,7 @@ void ASTCodeBlock::parseBlock() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTCodeBlock::ASTCodeBlock() {}
|
ASTCodeBlock::ASTCodeBlock() = default;
|
||||||
|
|
||||||
ASTCodeBlock::ASTCodeBlock(std::vector<std::string> in) : content(std::move(in)) {
|
ASTCodeBlock::ASTCodeBlock(std::vector<std::string> in) : content(std::move(in)) {
|
||||||
parseBlock();
|
parseBlock();
|
||||||
|
|||||||
@@ -13,14 +13,24 @@ class ASTCodeBlock;
|
|||||||
class ASTIdentifier;
|
class ASTIdentifier;
|
||||||
|
|
||||||
typedef std::variant<std::shared_ptr<ASTValue>, std::shared_ptr<ASTFunction>, std::shared_ptr<ASTFunctionCall>, std::shared_ptr<ASTCodeBlock>, std::shared_ptr<ASTIdentifier>> ASTNode;
|
typedef std::variant<std::shared_ptr<ASTValue>, std::shared_ptr<ASTFunction>, std::shared_ptr<ASTFunctionCall>, std::shared_ptr<ASTCodeBlock>, std::shared_ptr<ASTIdentifier>> ASTNode;
|
||||||
typedef std::variant<long long, double, std::string, bool> RealValue;
|
|
||||||
|
class ASTList {
|
||||||
|
private:
|
||||||
|
std::vector<ASTNode> elements;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ASTList(std::vector<ASTNode> in);
|
||||||
|
std::vector<ASTNode> getElements() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::variant<long long, double, std::string, bool, ASTList> RealValue;
|
||||||
|
|
||||||
enum class ValueType {
|
enum class ValueType {
|
||||||
Int, Float, String, Bool, None
|
Int, Float, String, Bool, List, None
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TokenType {
|
enum class TokenType {
|
||||||
Identifier, Value, Function, FunctionCallStart, OpenParen, CloseParen, CodeBlockStart, CodeBlockEnd, NewLine, None
|
Identifier, Value, Function, FunctionCallStart, OpenParen, CloseParen, CodeBlockStart, CodeBlockEnd, NewLine, ListStart, ListEnd, None
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,14 +47,16 @@ private:
|
|||||||
public:
|
public:
|
||||||
ValueType type;
|
ValueType type;
|
||||||
ValueType getValueType(std::string in);
|
ValueType getValueType(std::string in);
|
||||||
std::optional<std::string> getString();
|
std::optional<std::string> getString() const;
|
||||||
std::optional<int> getInt();
|
std::optional<int> getInt() const;
|
||||||
std::optional<double> getFloat();
|
std::optional<double> getFloat() const;
|
||||||
std::optional<bool> getBool();
|
std::optional<bool> getBool() const;
|
||||||
|
std::optional<ASTList> getList() const;
|
||||||
explicit ASTValue(std::string in);
|
explicit ASTValue(std::string in);
|
||||||
explicit ASTValue(long long in);
|
explicit ASTValue(long long in);
|
||||||
explicit ASTValue(double in);
|
explicit ASTValue(double in);
|
||||||
explicit ASTValue(bool in);
|
explicit ASTValue(bool in);
|
||||||
|
explicit ASTValue(ASTList in);
|
||||||
ASTValue();
|
ASTValue();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,4 +107,4 @@ class ASTIdentifier {
|
|||||||
explicit ASTIdentifier(std::string in);
|
explicit ASTIdentifier(std::string in);
|
||||||
};
|
};
|
||||||
|
|
||||||
ASTNode parser(std::vector<std::string> in);
|
ASTNode parser(std::vector<std::string> in);
|
||||||
@@ -17,6 +17,71 @@ std::map<std::string, Object> Executor::getVariables() {
|
|||||||
|
|
||||||
std::map<std::string, Object> globalVariables;
|
std::map<std::string, Object> globalVariables;
|
||||||
|
|
||||||
|
void Executor::printValue(const ASTValue& arg) {
|
||||||
|
if (arg.type == ValueType::String) {
|
||||||
|
std::optional<std::string> argString = arg.getString();
|
||||||
|
if (argString.has_value()) {
|
||||||
|
std::cout << argString.value();
|
||||||
|
} else {
|
||||||
|
std::cout << "Type mismatch - expecting string but got something else";
|
||||||
|
}
|
||||||
|
} else if (arg.type == ValueType::Int) {
|
||||||
|
std::optional<int> argInt = arg.getInt();
|
||||||
|
if (argInt.has_value()) {
|
||||||
|
std::cout << argInt.value();
|
||||||
|
} else {
|
||||||
|
std::cout << "Type mismatch - expecting int but got something else";
|
||||||
|
}
|
||||||
|
} else if (arg.type == ValueType::Float) {
|
||||||
|
std::optional<double> argFloat = arg.getFloat();
|
||||||
|
if (argFloat.has_value()) {
|
||||||
|
std::cout << argFloat.value();
|
||||||
|
} else {
|
||||||
|
std::cout << "Type mismatch - expecting float but got something else";
|
||||||
|
}
|
||||||
|
} else if (arg.type == ValueType::Bool) {
|
||||||
|
std::optional<bool> argBool = arg.getBool();
|
||||||
|
if (argBool.has_value()) {
|
||||||
|
std::cout << (argBool.value() ? "true" : "false");
|
||||||
|
} else {
|
||||||
|
std::cout << "Type mismatch - expecting bool but got something else";
|
||||||
|
}
|
||||||
|
} else if (arg.type == ValueType::List) {
|
||||||
|
std::optional<ASTList> list = arg.getList();
|
||||||
|
if (list.has_value()) {
|
||||||
|
std::cout << "[";
|
||||||
|
auto elements = list.value().getElements();
|
||||||
|
for (size_t i = 0; i < elements.size(); ++i) {
|
||||||
|
auto& node = elements[i];
|
||||||
|
if (std::holds_alternative<std::shared_ptr<ASTValue>>(node)) {
|
||||||
|
printValue(*std::get<std::shared_ptr<ASTValue>>(node));
|
||||||
|
} else if (std::holds_alternative<std::shared_ptr<ASTIdentifier>>(node)) {
|
||||||
|
auto name = std::get<std::shared_ptr<ASTIdentifier>>(node)->name;
|
||||||
|
if (variables.count(name)) {
|
||||||
|
Object obj = variables[name];
|
||||||
|
if (!obj.isCustomObject && std::holds_alternative<ASTValue>(obj.value)) {
|
||||||
|
printValue(std::get<ASTValue>(obj.value));
|
||||||
|
} else {
|
||||||
|
std::cout << "<function>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "<undefined variable: " << name << ">";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "<unprintable>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < elements.size() - 1) {
|
||||||
|
std::cout << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "]";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "Type mismatch - expecting string, int, float, bool or list but got something else";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<ASTNode> Executor::consume() {
|
std::optional<ASTNode> Executor::consume() {
|
||||||
if (iterator < code.nodes.size()) {
|
if (iterator < code.nodes.size()) {
|
||||||
return code.nodes[iterator++];
|
return code.nodes[iterator++];
|
||||||
@@ -184,40 +249,9 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
|||||||
ASTValue arg;
|
ASTValue arg;
|
||||||
if (object.isCustomObject == false && std::holds_alternative<ASTValue>(object.value)) {
|
if (object.isCustomObject == false && std::holds_alternative<ASTValue>(object.value)) {
|
||||||
arg = std::get<ASTValue>(object.value);
|
arg = std::get<ASTValue>(object.value);
|
||||||
|
printValue(arg);
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl;
|
std::cout << "Type mismatch - expecting printable value but got something else";
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (arg.type == ValueType::String) {
|
|
||||||
std::optional<std::string> argString = arg.getString();
|
|
||||||
if (argString.has_value()) {
|
|
||||||
std::cout << argString.value();
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting string but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else if (arg.type == ValueType::Int) {
|
|
||||||
std::optional<int> argInt = arg.getInt();
|
|
||||||
if (argInt.has_value()) {
|
|
||||||
std::cout << argInt.value();
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting int but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else if (arg.type == ValueType::Float) {
|
|
||||||
std::optional<double> argFloat = arg.getFloat();
|
|
||||||
if (argFloat.has_value()) {
|
|
||||||
std::cout << argFloat.value();
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting float but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else if (arg.type == ValueType::Bool) {
|
|
||||||
std::optional<bool> argBool = arg.getBool();
|
|
||||||
if (argBool.has_value()) {
|
|
||||||
std::cout << argBool.value();
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting bool but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (fnName == "println") {
|
} else if (fnName == "println") {
|
||||||
@@ -225,40 +259,10 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
|||||||
ASTValue arg;
|
ASTValue arg;
|
||||||
if (object.isCustomObject == false && std::holds_alternative<ASTValue>(object.value)) {
|
if (object.isCustomObject == false && std::holds_alternative<ASTValue>(object.value)) {
|
||||||
arg = std::get<ASTValue>(object.value);
|
arg = std::get<ASTValue>(object.value);
|
||||||
|
printValue(arg);
|
||||||
|
std::cout << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl;
|
std::cout << "Type mismatch - expecting printable value but got something else" << std::endl;
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (arg.type == ValueType::String) {
|
|
||||||
std::optional<std::string> argString = arg.getString();
|
|
||||||
if (argString.has_value()) {
|
|
||||||
std::cout << argString.value() << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting string but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else if (arg.type == ValueType::Int) {
|
|
||||||
std::optional<int> argInt = arg.getInt();
|
|
||||||
if (argInt.has_value()) {
|
|
||||||
std::cout << argInt.value() << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting int but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else if (arg.type == ValueType::Float) {
|
|
||||||
std::optional<double> argFloat = arg.getFloat();
|
|
||||||
if (argFloat.has_value()) {
|
|
||||||
std::cout << argFloat.value() << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting float but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else if (arg.type == ValueType::Bool) {
|
|
||||||
std::optional<bool> argBool = arg.getBool();
|
|
||||||
if (argBool.has_value()) {
|
|
||||||
std::cout << (argBool.value() ? "true" : "false") << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting bool but got something else" << std::endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cout << "Type mismatch - expecting string, int, float, or bool but got something else" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (fnName == "if") {
|
} else if (fnName == "if") {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class Executor {
|
|||||||
size_t iterator = 0;
|
size_t iterator = 0;
|
||||||
std::optional<ASTNode> consume();
|
std::optional<ASTNode> consume();
|
||||||
std::optional<ASTNode> peek(int ahead = 1);
|
std::optional<ASTNode> peek(int ahead = 1);
|
||||||
|
void printValue(const ASTValue& arg);
|
||||||
public:
|
public:
|
||||||
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
|
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
|
||||||
std::map<std::string, Object> getVariables();
|
std::map<std::string, Object> getVariables();
|
||||||
|
|||||||
Reference in New Issue
Block a user