Basic list support
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
class Lexer {
|
||||
private:
|
||||
std::vector<char> delimiters = {
|
||||
'(', ')', '{', '}', '.', '\n', ' '
|
||||
'(', ')', '{', '}', '[', ']', '.', '\n', ' ', ','
|
||||
};
|
||||
std::string file;
|
||||
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(long long in) : type(ValueType::Int), 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) {
|
||||
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)) {}
|
||||
|
||||
|
||||
std::optional<std::string> ASTValue::getString() {
|
||||
std::optional<std::string> ASTValue::getString() const {
|
||||
if (type == ValueType::String && std::holds_alternative<std::string>(value)) {
|
||||
return std::get<std::string>(value);
|
||||
} 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)) {
|
||||
return std::get<long long>(value);
|
||||
} 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)) {
|
||||
return std::get<double>(value);
|
||||
} 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)) {
|
||||
return std::get<bool>(value);
|
||||
} 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() {
|
||||
if (iterator < content.size()) {
|
||||
return content[iterator++]; // Post-increment: returns current, then increments
|
||||
@@ -132,6 +147,12 @@ TokenType ASTCodeBlock::getTokenType() {
|
||||
if (token == ")") {
|
||||
return TokenType::CloseParen;
|
||||
}
|
||||
if (token == "[") {
|
||||
return TokenType::ListStart;
|
||||
}
|
||||
if (token == "]") {
|
||||
return TokenType::ListEnd;
|
||||
}
|
||||
if (token == "\n") {
|
||||
return TokenType::NewLine;
|
||||
}
|
||||
@@ -288,6 +309,40 @@ void ASTCodeBlock::parseBlock() {
|
||||
nodes.emplace_back(std::make_shared<ASTCodeBlock>(body));
|
||||
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:
|
||||
break;
|
||||
}
|
||||
@@ -297,7 +352,7 @@ void ASTCodeBlock::parseBlock() {
|
||||
}
|
||||
}
|
||||
|
||||
ASTCodeBlock::ASTCodeBlock() {}
|
||||
ASTCodeBlock::ASTCodeBlock() = default;
|
||||
|
||||
ASTCodeBlock::ASTCodeBlock(std::vector<std::string> in) : content(std::move(in)) {
|
||||
parseBlock();
|
||||
|
||||
@@ -13,14 +13,24 @@ class ASTCodeBlock;
|
||||
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<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 {
|
||||
Int, Float, String, Bool, None
|
||||
Int, Float, String, Bool, List, None
|
||||
};
|
||||
|
||||
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:
|
||||
ValueType type;
|
||||
ValueType getValueType(std::string in);
|
||||
std::optional<std::string> getString();
|
||||
std::optional<int> getInt();
|
||||
std::optional<double> getFloat();
|
||||
std::optional<bool> getBool();
|
||||
std::optional<std::string> getString() const;
|
||||
std::optional<int> getInt() const;
|
||||
std::optional<double> getFloat() const;
|
||||
std::optional<bool> getBool() const;
|
||||
std::optional<ASTList> getList() const;
|
||||
explicit ASTValue(std::string in);
|
||||
explicit ASTValue(long long in);
|
||||
explicit ASTValue(double in);
|
||||
explicit ASTValue(bool in);
|
||||
explicit ASTValue(ASTList in);
|
||||
ASTValue();
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,71 @@ std::map<std::string, Object> Executor::getVariables() {
|
||||
|
||||
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() {
|
||||
if (iterator < code.nodes.size()) {
|
||||
return code.nodes[iterator++];
|
||||
@@ -184,40 +249,9 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
||||
ASTValue arg;
|
||||
if (object.isCustomObject == false && std::holds_alternative<ASTValue>(object.value)) {
|
||||
arg = std::get<ASTValue>(object.value);
|
||||
printValue(arg);
|
||||
} else {
|
||||
std::cout << "Type mismatch - expecting string, int, float, or bool 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();
|
||||
} 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;
|
||||
std::cout << "Type mismatch - expecting printable value but got something else";
|
||||
}
|
||||
}
|
||||
} else if (fnName == "println") {
|
||||
@@ -225,40 +259,10 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
||||
ASTValue arg;
|
||||
if (object.isCustomObject == false && std::holds_alternative<ASTValue>(object.value)) {
|
||||
arg = std::get<ASTValue>(object.value);
|
||||
printValue(arg);
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
std::cout << "Type mismatch - expecting string, int, float, or bool 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;
|
||||
std::cout << "Type mismatch - expecting printable value but got something else" << std::endl;
|
||||
}
|
||||
}
|
||||
} else if (fnName == "if") {
|
||||
|
||||
@@ -35,6 +35,7 @@ class Executor {
|
||||
size_t iterator = 0;
|
||||
std::optional<ASTNode> consume();
|
||||
std::optional<ASTNode> peek(int ahead = 1);
|
||||
void printValue(const ASTValue& arg);
|
||||
public:
|
||||
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
|
||||
std::map<std::string, Object> getVariables();
|
||||
|
||||
Reference in New Issue
Block a user