Simple list implementation
This commit is contained in:
53
src/datatypes/lists.cpp
Normal file
53
src/datatypes/lists.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "lists.h"
|
||||
|
||||
// Helper to trim whitespace from the start and end of a string
|
||||
std::string trim(const std::string& str) {
|
||||
size_t first = str.find_first_not_of(" \t\n\r");
|
||||
if (std::string::npos == first) {
|
||||
return str;
|
||||
}
|
||||
size_t last = str.find_last_not_of(" \t\n\r");
|
||||
return str.substr(first, (last - first + 1));
|
||||
}
|
||||
|
||||
std::vector<Value> parse_list_content(const std::string& content) {
|
||||
std::vector<Value> items;
|
||||
std::string current_item;
|
||||
bool in_string = false;
|
||||
int nested_level = 0;
|
||||
|
||||
for (char c : content) {
|
||||
if (c == '"') {
|
||||
in_string = !in_string;
|
||||
}
|
||||
|
||||
if (c == ',' && !in_string && nested_level == 0) {
|
||||
// End of an item
|
||||
std::string trimmed = trim(current_item);
|
||||
if (!trimmed.empty()) {
|
||||
if (trimmed.front() == '"' && trimmed.back() == '"') {
|
||||
items.push_back(Value(trimmed.substr(1, trimmed.length() - 2)));
|
||||
} else {
|
||||
items.push_back(Value(trimmed));
|
||||
}
|
||||
}
|
||||
current_item.clear();
|
||||
} else {
|
||||
if (c == '[' || c == '(') nested_level++;
|
||||
if (c == ']' || c == ')') nested_level--;
|
||||
current_item += c;
|
||||
}
|
||||
}
|
||||
|
||||
// Last item
|
||||
std::string trimmed = trim(current_item);
|
||||
if (!trimmed.empty()) {
|
||||
if (trimmed.front() == '"' && trimmed.back() == '"') {
|
||||
items.push_back(Value(trimmed.substr(1, trimmed.length() - 2)));
|
||||
} else {
|
||||
items.push_back(Value(trimmed));
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
8
src/datatypes/lists.h
Normal file
8
src/datatypes/lists.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../defs/defs.h"
|
||||
|
||||
std::vector<Value> parse_list_content(const std::string& content);
|
||||
std::string trim(const std::string& str);
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include "../datatypes/lists.h"
|
||||
|
||||
InstructionType strToInstructionType(std::string in) {
|
||||
if (in == "println") return InstructionType::Println;
|
||||
@@ -16,6 +17,7 @@ InstructionType strToInstructionType(std::string in) {
|
||||
else if (in == "compare") return InstructionType::Compare;
|
||||
else if (in == "input") return InstructionType::Input;
|
||||
else if (in == "return") return InstructionType::Return;
|
||||
else if (in == "concat") return InstructionType::Concat;
|
||||
else return InstructionType::Variable;
|
||||
}
|
||||
|
||||
@@ -69,7 +71,9 @@ Value::Value() : valtype(ValueType::Real) {}
|
||||
|
||||
Value::Value(InstructionGroup instgroup) : valtype(ValueType::InstructionGroup), instructionGroup(instgroup) {};
|
||||
|
||||
Value::Value(const Value& other) : valtype(other.valtype), real(other.real), varName(other.varName), instructionGroup(other.instructionGroup) {
|
||||
Value::Value(std::vector<Value> listval) : valtype(ValueType::List), list(std::move(listval)) {}
|
||||
|
||||
Value::Value(const Value& other) : valtype(other.valtype), real(other.real), varName(other.varName), instructionGroup(other.instructionGroup), list(other.list) {
|
||||
if (other.processed) {
|
||||
processed = std::make_unique<Instruction>(*other.processed);
|
||||
}
|
||||
@@ -86,6 +90,7 @@ Value& Value::operator=(const Value& other) {
|
||||
real = other.real;
|
||||
varName = other.varName;
|
||||
instructionGroup = other.instructionGroup;
|
||||
list = other.list;
|
||||
if (other.processed) {
|
||||
processed = std::make_unique<Instruction>(*other.processed);
|
||||
} else {
|
||||
@@ -113,6 +118,14 @@ std::string Value::toString() const {
|
||||
case ValueType::InstructionGroup:
|
||||
out += "InstructionGroup, contains " + std::to_string(instructionGroup.size()) + " instructions)";
|
||||
break;
|
||||
case ValueType::List: {
|
||||
out += "List, items: [";
|
||||
for (const auto& item : list) {
|
||||
out += item.toString() + ", ";
|
||||
}
|
||||
out += "])";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
out += "FIXME)";
|
||||
break;
|
||||
@@ -161,6 +174,8 @@ std::vector<Value> split(std::string line) {
|
||||
std::string buf;
|
||||
bool instring = false;
|
||||
int brackets = 0;
|
||||
char bracket_type = 0;
|
||||
|
||||
for (char chr : line) {
|
||||
if (chr == ' ' && !instring && brackets == 0 && !buf.empty()) {
|
||||
if (buf[0] == '$') {
|
||||
@@ -170,8 +185,8 @@ std::vector<Value> split(std::string line) {
|
||||
}
|
||||
buf = "";
|
||||
} else if (chr == '(' || chr == '[') {
|
||||
brackets += 1;
|
||||
if (brackets == 1) {
|
||||
if (brackets == 0) {
|
||||
bracket_type = chr;
|
||||
if (!buf.empty()) {
|
||||
splitvals.push_back(Value(buf));
|
||||
buf = "";
|
||||
@@ -179,13 +194,20 @@ std::vector<Value> split(std::string line) {
|
||||
} else {
|
||||
buf += chr;
|
||||
}
|
||||
brackets++;
|
||||
} else if (chr == ')' || chr == ']') {
|
||||
brackets -= 1;
|
||||
brackets--;
|
||||
if (brackets == 0) {
|
||||
if (!buf.empty()) {
|
||||
if (bracket_type == '(') {
|
||||
splitvals.push_back(Value(Instruction(split(buf))));
|
||||
} else {
|
||||
splitvals.push_back(Value(parse_list_content(buf)));
|
||||
}
|
||||
buf = "";
|
||||
}
|
||||
} else {
|
||||
buf += chr;
|
||||
}
|
||||
} else if (chr == '"') {
|
||||
instring = !instring;
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
|
||||
enum class InstructionType {
|
||||
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Return
|
||||
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Return, Concat
|
||||
};
|
||||
|
||||
enum class ValueType {
|
||||
Real, Processed, Variable, InstructionGroup
|
||||
Real, Processed, Variable, InstructionGroup, List, Map
|
||||
};
|
||||
|
||||
struct Instruction;
|
||||
@@ -33,12 +33,14 @@ struct Value {
|
||||
std::unique_ptr<Instruction> processed;
|
||||
std::string real = "";
|
||||
InstructionGroup instructionGroup;
|
||||
std::vector<Value> list;
|
||||
bool is_return = false;
|
||||
std::string toString() const;
|
||||
Varname varName = Varname();
|
||||
Value(std::string stringval);
|
||||
Value(Instruction instval);
|
||||
Value(InstructionGroup instgroup);
|
||||
Value(std::vector<Value> listval);
|
||||
Value(Varname var);
|
||||
Value();
|
||||
Value(const Value& other);
|
||||
@@ -58,4 +60,5 @@ struct Instruction {
|
||||
|
||||
std::vector<Value> split(std::string in);
|
||||
InstructionType strToInstructionType(std::string in);
|
||||
std::string trim(const std::string& str);
|
||||
extern bool inReplMode;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "../modules/compare/compare.h"
|
||||
#include "../modules/input/input.h"
|
||||
#include "../modules/function/function.h"
|
||||
#include "../modules/concat/concat.h"
|
||||
|
||||
Value execute(Instruction inst) {
|
||||
// Special cases that need to manage their own argument evaluation
|
||||
@@ -68,6 +69,9 @@ Value execute(Instruction inst) {
|
||||
case InstructionType::Exit:
|
||||
return modules::exit(inst.args);
|
||||
break;
|
||||
case InstructionType::Concat:
|
||||
return modules::concat(inst.args);
|
||||
break;
|
||||
case InstructionType::Variable: {
|
||||
if (!inst.args.empty()) {
|
||||
const std::string& name = inst.args[0].real;
|
||||
|
||||
16
src/modules/concat/concat.cpp
Normal file
16
src/modules/concat/concat.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "concat.h"
|
||||
#include "../../defs/defs.h"
|
||||
#include "../../error/error.h"
|
||||
#include <vector>
|
||||
|
||||
Value modules::concat(std::vector<Value> args) {
|
||||
std::string buf;
|
||||
for (Value val : args) {
|
||||
if (val.valtype == ValueType::Real) {
|
||||
buf += val.real;
|
||||
} else {
|
||||
error("Can only concatenate real values");
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
8
src/modules/concat/concat.h
Normal file
8
src/modules/concat/concat.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../defs/defs.h"
|
||||
#include <vector>
|
||||
|
||||
namespace modules {
|
||||
Value concat(std::vector<Value> args);
|
||||
}
|
||||
@@ -8,7 +8,22 @@
|
||||
Value modules::print(std::vector<Value> values) {
|
||||
for (Value value : values) {
|
||||
if (value.valtype == ValueType::Real) {
|
||||
std::cout << value.real << " ";
|
||||
std::cout << value.real;
|
||||
if (values.size() > 1) {
|
||||
std::cout << " ";
|
||||
}
|
||||
} else if (value.valtype == ValueType::List) {
|
||||
std::cout << "[";
|
||||
bool afterfirst = false;
|
||||
for (Value val : value.list) {
|
||||
if (afterfirst) {
|
||||
std::cout << ", ";
|
||||
} else {
|
||||
afterfirst = true;
|
||||
}
|
||||
print({val});
|
||||
}
|
||||
std::cout << "]";
|
||||
} else {
|
||||
error("FIXME unprocessed processed (in print module)");
|
||||
}
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
#include "println.h"
|
||||
#include "../../defs/defs.h"
|
||||
#include "../../error/error.h"
|
||||
#include "../print/print.h"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
Value modules::println(std::vector<Value> values) {
|
||||
for (Value value : values) {
|
||||
if (value.valtype == ValueType::Real) {
|
||||
std::cout << value.real << " ";
|
||||
} else {
|
||||
error("FIXME unprocessed processed (in println module)");
|
||||
}
|
||||
}
|
||||
print(values);
|
||||
std::cout << "\n";
|
||||
return Value("");
|
||||
}
|
||||
|
||||
8
src/modules/split/split.cpp
Normal file
8
src/modules/split/split.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "split.h"
|
||||
#include "../../defs/defs.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
Value modules::split(std::vector<Value> args) {
|
||||
return Value("Work in progress!");
|
||||
}
|
||||
8
src/modules/split/split.h
Normal file
8
src/modules/split/split.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../defs/defs.h"
|
||||
#include <vector>
|
||||
|
||||
namespace modules {
|
||||
Value split(std::vector<Value> args);
|
||||
}
|
||||
@@ -3,16 +3,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Helper to trim whitespace
|
||||
std::string trim(const std::string& str) {
|
||||
size_t first = str.find_first_not_of(" \t\n\r");
|
||||
if (std::string::npos == first) {
|
||||
return str;
|
||||
}
|
||||
size_t last = str.find_last_not_of(" \t\n\r");
|
||||
return str.substr(first, (last - first + 1));
|
||||
}
|
||||
|
||||
std::vector<Instruction> parse(std::string program) {
|
||||
std::vector<Instruction> instructions;
|
||||
std::vector<std::string> lines;
|
||||
|
||||
Reference in New Issue
Block a user