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 <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include "../datatypes/lists.h"
|
||||||
|
|
||||||
InstructionType strToInstructionType(std::string in) {
|
InstructionType strToInstructionType(std::string in) {
|
||||||
if (in == "println") return InstructionType::Println;
|
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 == "compare") return InstructionType::Compare;
|
||||||
else if (in == "input") return InstructionType::Input;
|
else if (in == "input") return InstructionType::Input;
|
||||||
else if (in == "return") return InstructionType::Return;
|
else if (in == "return") return InstructionType::Return;
|
||||||
|
else if (in == "concat") return InstructionType::Concat;
|
||||||
else return InstructionType::Variable;
|
else return InstructionType::Variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +71,9 @@ Value::Value() : valtype(ValueType::Real) {}
|
|||||||
|
|
||||||
Value::Value(InstructionGroup instgroup) : valtype(ValueType::InstructionGroup), instructionGroup(instgroup) {};
|
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) {
|
if (other.processed) {
|
||||||
processed = std::make_unique<Instruction>(*other.processed);
|
processed = std::make_unique<Instruction>(*other.processed);
|
||||||
}
|
}
|
||||||
@@ -86,6 +90,7 @@ Value& Value::operator=(const Value& other) {
|
|||||||
real = other.real;
|
real = other.real;
|
||||||
varName = other.varName;
|
varName = other.varName;
|
||||||
instructionGroup = other.instructionGroup;
|
instructionGroup = other.instructionGroup;
|
||||||
|
list = other.list;
|
||||||
if (other.processed) {
|
if (other.processed) {
|
||||||
processed = std::make_unique<Instruction>(*other.processed);
|
processed = std::make_unique<Instruction>(*other.processed);
|
||||||
} else {
|
} else {
|
||||||
@@ -113,6 +118,14 @@ std::string Value::toString() const {
|
|||||||
case ValueType::InstructionGroup:
|
case ValueType::InstructionGroup:
|
||||||
out += "InstructionGroup, contains " + std::to_string(instructionGroup.size()) + " instructions)";
|
out += "InstructionGroup, contains " + std::to_string(instructionGroup.size()) + " instructions)";
|
||||||
break;
|
break;
|
||||||
|
case ValueType::List: {
|
||||||
|
out += "List, items: [";
|
||||||
|
for (const auto& item : list) {
|
||||||
|
out += item.toString() + ", ";
|
||||||
|
}
|
||||||
|
out += "])";
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
out += "FIXME)";
|
out += "FIXME)";
|
||||||
break;
|
break;
|
||||||
@@ -161,6 +174,8 @@ std::vector<Value> split(std::string line) {
|
|||||||
std::string buf;
|
std::string buf;
|
||||||
bool instring = false;
|
bool instring = false;
|
||||||
int brackets = 0;
|
int brackets = 0;
|
||||||
|
char bracket_type = 0;
|
||||||
|
|
||||||
for (char chr : line) {
|
for (char chr : line) {
|
||||||
if (chr == ' ' && !instring && brackets == 0 && !buf.empty()) {
|
if (chr == ' ' && !instring && brackets == 0 && !buf.empty()) {
|
||||||
if (buf[0] == '$') {
|
if (buf[0] == '$') {
|
||||||
@@ -170,8 +185,8 @@ std::vector<Value> split(std::string line) {
|
|||||||
}
|
}
|
||||||
buf = "";
|
buf = "";
|
||||||
} else if (chr == '(' || chr == '[') {
|
} else if (chr == '(' || chr == '[') {
|
||||||
brackets += 1;
|
if (brackets == 0) {
|
||||||
if (brackets == 1) {
|
bracket_type = chr;
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
splitvals.push_back(Value(buf));
|
splitvals.push_back(Value(buf));
|
||||||
buf = "";
|
buf = "";
|
||||||
@@ -179,13 +194,20 @@ std::vector<Value> split(std::string line) {
|
|||||||
} else {
|
} else {
|
||||||
buf += chr;
|
buf += chr;
|
||||||
}
|
}
|
||||||
|
brackets++;
|
||||||
} else if (chr == ')' || chr == ']') {
|
} else if (chr == ')' || chr == ']') {
|
||||||
brackets -= 1;
|
brackets--;
|
||||||
if (brackets == 0) {
|
if (brackets == 0) {
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
splitvals.push_back(Value(Instruction(split(buf))));
|
if (bracket_type == '(') {
|
||||||
|
splitvals.push_back(Value(Instruction(split(buf))));
|
||||||
|
} else {
|
||||||
|
splitvals.push_back(Value(parse_list_content(buf)));
|
||||||
|
}
|
||||||
buf = "";
|
buf = "";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
buf += chr;
|
||||||
}
|
}
|
||||||
} else if (chr == '"') {
|
} else if (chr == '"') {
|
||||||
instring = !instring;
|
instring = !instring;
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
|
|
||||||
enum class InstructionType {
|
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 {
|
enum class ValueType {
|
||||||
Real, Processed, Variable, InstructionGroup
|
Real, Processed, Variable, InstructionGroup, List, Map
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Instruction;
|
struct Instruction;
|
||||||
@@ -33,12 +33,14 @@ struct Value {
|
|||||||
std::unique_ptr<Instruction> processed;
|
std::unique_ptr<Instruction> processed;
|
||||||
std::string real = "";
|
std::string real = "";
|
||||||
InstructionGroup instructionGroup;
|
InstructionGroup instructionGroup;
|
||||||
|
std::vector<Value> list;
|
||||||
bool is_return = false;
|
bool is_return = false;
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
Varname varName = Varname();
|
Varname varName = Varname();
|
||||||
Value(std::string stringval);
|
Value(std::string stringval);
|
||||||
Value(Instruction instval);
|
Value(Instruction instval);
|
||||||
Value(InstructionGroup instgroup);
|
Value(InstructionGroup instgroup);
|
||||||
|
Value(std::vector<Value> listval);
|
||||||
Value(Varname var);
|
Value(Varname var);
|
||||||
Value();
|
Value();
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
@@ -58,4 +60,5 @@ struct Instruction {
|
|||||||
|
|
||||||
std::vector<Value> split(std::string in);
|
std::vector<Value> split(std::string in);
|
||||||
InstructionType strToInstructionType(std::string in);
|
InstructionType strToInstructionType(std::string in);
|
||||||
|
std::string trim(const std::string& str);
|
||||||
extern bool inReplMode;
|
extern bool inReplMode;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "../modules/compare/compare.h"
|
#include "../modules/compare/compare.h"
|
||||||
#include "../modules/input/input.h"
|
#include "../modules/input/input.h"
|
||||||
#include "../modules/function/function.h"
|
#include "../modules/function/function.h"
|
||||||
|
#include "../modules/concat/concat.h"
|
||||||
|
|
||||||
Value execute(Instruction inst) {
|
Value execute(Instruction inst) {
|
||||||
// Special cases that need to manage their own argument evaluation
|
// Special cases that need to manage their own argument evaluation
|
||||||
@@ -68,6 +69,9 @@ Value execute(Instruction inst) {
|
|||||||
case InstructionType::Exit:
|
case InstructionType::Exit:
|
||||||
return modules::exit(inst.args);
|
return modules::exit(inst.args);
|
||||||
break;
|
break;
|
||||||
|
case InstructionType::Concat:
|
||||||
|
return modules::concat(inst.args);
|
||||||
|
break;
|
||||||
case InstructionType::Variable: {
|
case InstructionType::Variable: {
|
||||||
if (!inst.args.empty()) {
|
if (!inst.args.empty()) {
|
||||||
const std::string& name = inst.args[0].real;
|
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) {
|
Value modules::print(std::vector<Value> values) {
|
||||||
for (Value value : values) {
|
for (Value value : values) {
|
||||||
if (value.valtype == ValueType::Real) {
|
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 {
|
} else {
|
||||||
error("FIXME unprocessed processed (in print module)");
|
error("FIXME unprocessed processed (in print module)");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
#include "println.h"
|
#include "println.h"
|
||||||
#include "../../defs/defs.h"
|
#include "../../defs/defs.h"
|
||||||
#include "../../error/error.h"
|
#include "../print/print.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
Value modules::println(std::vector<Value> values) {
|
Value modules::println(std::vector<Value> values) {
|
||||||
for (Value value : values) {
|
print(values);
|
||||||
if (value.valtype == ValueType::Real) {
|
|
||||||
std::cout << value.real << " ";
|
|
||||||
} else {
|
|
||||||
error("FIXME unprocessed processed (in println module)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
return Value("");
|
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 <string>
|
||||||
#include <vector>
|
#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> parse(std::string program) {
|
||||||
std::vector<Instruction> instructions;
|
std::vector<Instruction> instructions;
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
|
|||||||
Reference in New Issue
Block a user