2 Commits

Author SHA1 Message Date
e5a39f07fb Update .gitignore 2025-10-13 09:17:54 +11:00
fa5d805eef Refactoring (MAY BE BUGGY) 2025-10-13 09:16:28 +11:00
21 changed files with 2954 additions and 2929 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
ground
Bobfile
build

View File

@@ -1,5 +0,0 @@
compiler "g++";
binary "ground";
source "src/main.cpp";
flag "Ofast";
compile;

22
Makefile Normal file
View File

@@ -0,0 +1,22 @@
CXX = g++
CXXFLAGS = -O3 -Isrc -Wall -Wextra -std=c++17
BUILD_DIR = build
SRCS = $(shell find src -name '*.cpp')
VPATH = $(sort $(dir $(SRCS)))
OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(SRCS:.cpp=.o)))
TARGET = ground
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)
$(BUILD_DIR)/%.o: %.cpp
@mkdir -p $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -rf $(BUILD_DIR) $(TARGET)
.PHONY: all clean

View File

@@ -13,13 +13,7 @@ Ground is an interpreter which processes and interprets Ground instructions. It
## How do I get started?
Clone the repo and compile with your favourite C++ compiler:
```
g++ src/main.cpp -std=c++17 -O3 -o ground
```
(You can omit the -std flag on systems which default to the latest standard, and the -O3 flag if you're fine with a slightly slower interpreter.)
Clone the repo and compile with `make`.
Run a Ground program:

244
src/data/data.cpp Normal file
View File

@@ -0,0 +1,244 @@
#include "data.h"
#include "../main.h"
#include "../error/error.h"
#include <string>
#include <vector>
#include <map>
#include <stack>
/*
labelStack stack
Allows each function to hold it's own set of labels
*/
std::stack<std::map<std::string, int>> labelStack;
/*
variables map
Contains all variables made while running the program. See also Literal struct.
*/
std::map<std::string, Literal> variables;
/*
functions map
Contains the code of functions and types of their values
*/
std::map<std::string, Function> functions;
/*
structs map
Contains structs (see the Struct struct for more info)
*/
std::map<std::string, Struct> structs;
/*
fnArgs vector
Containst the arguments to be passed to a function
*/
std::vector<Literal> fnArgs;
// External library functions and other things
// Handle to loaded libraries
std::map<std::string, void*> loadedLibraries;
// Map of function name to function pointer
std::map<std::string, void*> externalFunctions;
// Libraries currently imported
std::vector<std::string> libraries;
// Conversion functions
GroundValue literalToGroundValue(const Literal& lit) {
GroundValue gv;
if (std::holds_alternative<int>(lit.val)) {
gv.type = GROUND_INT;
gv.data.int_val = std::get<int>(lit.val);
} else if (std::holds_alternative<double>(lit.val)) {
gv.type = GROUND_DOUBLE;
gv.data.double_val = std::get<double>(lit.val);
} else if (std::holds_alternative<bool>(lit.val)) {
gv.type = GROUND_BOOL;
gv.data.bool_val = std::get<bool>(lit.val) ? 1 : 0;
} else if (std::holds_alternative<std::string>(lit.val)) {
gv.type = GROUND_STRING;
gv.data.string_val = const_cast<char*>(std::get<std::string>(lit.val).c_str());
} else if (std::holds_alternative<char>(lit.val)) {
gv.type = GROUND_CHAR;
gv.data.char_val = std::get<char>(lit.val);
}
return gv;
}
/*
catches stackmap
This stores all catches in a scope, to catch errors before they happen.
*/
std::stack<std::map<std::string, Direct>> catches;
Literal groundValueToLiteral(const GroundValue& gv) {
Literal lit;
switch (gv.type) {
case GROUND_INT:
lit.val = gv.data.int_val;
break;
case GROUND_DOUBLE:
lit.val = gv.data.double_val;
break;
case GROUND_BOOL:
lit.val = (gv.data.bool_val != 0);
break;
case GROUND_STRING:
lit.val = std::string(gv.data.string_val);
break;
case GROUND_CHAR:
lit.val = gv.data.char_val;
break;
}
return lit;
}
/*
is* functions
These functions determine if a string value can be converted into a different type.
*/
bool isInt(std::string in) {
try {
std::stoi(in);
if (std::stod(in) != std::stoi(in)) return false;
return true;
} catch (...) {
return false;
}
}
bool isDouble(std::string in) {
try {
std::stod(in);
return true;
} catch (...) {
return false;
}
}
bool isBool(std::string in) {
if (in == "true" || in == "false") return true;
else return false;
}
bool isString(std::string in) {
if (in.size() >= 2 && in[0] == '"' && in[in.size() - 1] == '"') return true;
else return false;
}
bool isChar(std::string in) {
if (in.size() == 3 && in[0] == '\'' && in[in.size() - 1] == '\'') return true;
else return false;
}
bool isValue(std::string in) {
if (in.size() >= 1 && in[0] == '$') return true;
else return false;
}
bool isDirect(std::string in) {
if (in.size() >= 1 && in[0] == '&') return true;
else return false;
}
bool isLine(std::string in) {
if (in.size() >= 1 && in[0] == '%') return true;
else return false;
}
bool isLabel(std::string in) {
if (in.size() >= 1 && in[0] == '@') return true;
else return false;
}
bool isType(std::string in) {
if (in.size() > 1 && in[0] == '-') return true;
else return false;
}
bool isFunction(std::string in) {
if (in.size() >= 1 && in[0] == '!') return true;
else return false;
}
bool isReferencingStruct(std::string in) {
return in.find('.') != std::string::npos;
}
/*
getType function
This function determines the type of a value inside a string based on the is*
functions above. Returns a type from the Types enum class.
*/
Types getType(std::string in) {
if (isInt(in)) return Types::Int;
if (isDouble(in)) return Types::Double;
if (isBool(in)) return Types::Bool;
if (isString(in)) return Types::String;
if (isChar(in)) return Types::Char;
if (isValue(in)) return Types::Value;
if (isDirect(in)) return Types::Direct;
if (isLine(in)) return Types::Line;
if (isLabel(in)) return Types::Label;
if (isType(in)) return Types::Type;
if (isFunction(in)) return Types::Function;
error("Could not determine type of \"" + in + "\"");
return Types::Int;
}
/*
getLitType function
This function determines the type of a value inside a Literal based on the
holds_alternative() function. Returns a type from the Types enum class.
*/
Types getLitType(Literal in) {
if (std::holds_alternative<int>(in.val)) return Types::Int;
if (std::holds_alternative<double>(in.val)) return Types::Double;
if (std::holds_alternative<bool>(in.val)) return Types::Bool;
if (std::holds_alternative<std::string>(in.val)) return Types::String;
if (std::holds_alternative<char>(in.val)) return Types::Char;
if (std::holds_alternative<List>(in.val)) return Types::List;
return Types::Other;
}
/*
setVal function
This function sets the value of a variable (whether in a struct or not).
*/
void setVal(std::string varName, Literal value) {
if (isReferencingStruct(varName)) {
std::string structName;
std::string varInStruct;
size_t dotPos = varName.find('.'); // Use size_t
if (dotPos != std::string::npos) {
structName = varName.substr(0, dotPos);
varInStruct = varName.substr(dotPos + 1);
if (variables.find(structName) != variables.end()) {
if (std::holds_alternative<Struct>(variables[structName].val)) {
Struct structVal = std::get<Struct>(variables[structName].val);
if (structVal.values.find(varInStruct) != structVal.values.end()) {
structVal.values[varInStruct] = value;
variables[structName].val = structVal; // Write back the modified struct
} else {
error("Could not find property '" + varInStruct + "' in struct '" + structName + "'");
}
} else {
error("Variable '" + structName + "' is not a struct");
}
} else {
error("Could not find struct '" + structName + "'");
}
} else {
error("Invalid struct member access syntax");
}
} else {
// Handle regular variables (both existing and new)
variables[varName] = value;
}
}

66
src/data/data.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include "../main.h"
#include <string>
#include <vector>
#include <map>
#include <stack>
/*
functions map
Contains the code of functions and types of their values
*/
extern std::map<std::string, Function> functions;
/*
structs map
Contains structs (see the Struct struct for more info)
*/
extern std::map<std::string, Struct> structs;
/*
fnArgs vector
Containst the arguments to be passed to a function
*/
extern std::vector<Literal> fnArgs;
// External library functions and other things
// Handle to loaded libraries
extern std::map<std::string, void*> loadedLibraries;
// Map of function name to function pointer
extern std::map<std::string, void*> externalFunctions;
// Libraries currently imported
extern std::vector<std::string> libraries;
// catches stackmap
extern std::stack<std::map<std::string, Direct>> catches;
// labelStack stack
extern std::stack<std::map<std::string, int>> labelStack;
// variables map
extern std::map<std::string, Literal> variables;
GroundValue literalToGroundValue(const Literal& lit);
Literal groundValueToLiteral(const GroundValue& gv);
void setVal(std::string varName, Literal value);
bool isInt(std::string in);
bool isDouble(std::string in);
bool isBool(std::string in);
bool isString(std::string in);
bool isChar(std::string in);
bool isValue(std::string in);
bool isDirect(std::string in);
bool isLine(std::string in);
bool isLabel(std::string in);
bool isType(std::string in);
bool isFunction(std::string in);
bool isReferencingStruct(std::string in);
Types getType(std::string in);
Types getLitType(Literal in);
void setVal(std::string varName, Literal value);

34
src/error/error.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include <iostream>
#include <cstdlib>
#include "error.h"
#include "../data/data.h"
#include "../main.h"
using namespace std;
/*
error function
Takes a string (which is a debug message) and prints it to the console, letting the
user know what went wrong with the program.
*/
Literal error(string in, string errCode, int exitc) {
Error retError;
retError.code = errCode;
retError.pops = 0;
while (catches.size() > 0) {
if (catches.top().find(errCode) != catches.top().end()) {
Literal tmpLit;
tmpLit.val = false;
setVal(catches.top()[errCode].varName, tmpLit);
retError.reporter = catches.top()[errCode].varName;
Literal tmpLit2;
tmpLit2.val = retError;
return tmpLit2;
} else {
catches.pop();
retError.pops ++;
}
}
cout << "\033[31m" + errCode + ": \033[39m" << in << endl;
exit(exitc);
}

6
src/error/error.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include "../main.h"
#include <string>
Literal error(std::string in, std::string errCode = "syntaxError", int exitc = 1);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
#pragma once
#include <vector>
#include "../main.h"
void preProcessLabels(std::vector<Instruction> instructions);
Literal exec(std::vector<Instruction> in, bool executingFunction = false);

81
src/lexer/lexer.cpp Normal file
View File

@@ -0,0 +1,81 @@
#include <vector>
#include <string>
#include "lexer.h"
using namespace std;
/*
lexer function
This function takes the raw text from the file and splits it into a format
that the parser can understand.
*/
vector<vector<string>> lexer(string in) {
vector<vector<string>> out;
vector<string> line;
string buf;
bool procString = false;
bool procChar = false;
bool isComment = false;
for (char i : in) {
switch (i) {
case '"':
if (!isComment) {
if (procChar) {
buf.push_back(i);
} else {
procString = !procString;
buf.push_back(i);
}
}
break;
case '\'':
if (!isComment) {
if (procString) {
buf.push_back(i);
} else {
procChar = !procChar;
buf.push_back(i);
}
}
break;
case '\n':
if (!procString && !procChar) {
if (!buf.empty()) line.push_back(buf);
out.push_back(line);
buf.clear();
line.clear();
isComment = false;
} else {
if (!isComment) buf.push_back(i);
}
break;
case '#':
if (!procString && !procChar) {
isComment = true;
if (!buf.empty()) line.push_back(buf);
out.push_back(line);
buf.clear();
line.clear();
} else {
buf.push_back(i);
}
break;
case ' ':
if (!procString && !procChar) {
if (!buf.empty() && !isComment) line.push_back(buf);
buf.clear();
} else {
buf.push_back(i);
}
break;
default:
if (!isComment) buf.push_back(i);
break;
}
}
if (!buf.empty()) line.push_back(buf);
out.push_back(line);
return out;
}

6
src/lexer/lexer.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include <vector>
#include <string>
std::vector<std::vector<std::string>> lexer(std::string in);

File diff suppressed because it is too large Load Diff

250
src/main.h Normal file
View File

@@ -0,0 +1,250 @@
#pragma once
#include <vector>
#include <string>
#include <map>
#include <variant>
// Headers for external libraries
#ifdef _WIN32
// Note: Windows support is experiemental. Maybe try using a superior
// operating system? (cough cough, Linux?)
#include <windows.h>
#define DLOPEN(path) LoadLibrary(path)
#define DLSYM(handle, name) GetProcAddress(handle, name)
#define DLCLOSE(handle) FreeLibrary(handle)
#define DLERROR() "Windows DLL Error"
#else
#include <dlfcn.h>
#define DLOPEN(path) dlopen(path, RTLD_LAZY)
#define DLSYM(handle, name) dlsym(handle, name)
#define DLCLOSE(handle) dlclose(handle)
#define DLERROR() dlerror()
#endif
/*
Instructions enum class
For each function keyword, an instruction is assigned. See also parser
function, interpreter function, Instruction struct
*/
enum class Instructions {
Jump, If,
Stdout, Stdin, Stdlnout,
Add, Subtract, Multiply, Divide,
Equal, Inequal, Greater, Lesser, Not,
End, Set, Empty, Gettype, Exists,
Setlist, Getlistat, Setlistat, Getlistsize, Listappend, Listprepend,
Getstrcharat, Getstrsize,
Stoi, Stod, Tostring,
Fun, Return, Endfun, Pusharg, Call, Local,
Use, Extern, Error, Catch, Try, Exception,
Struct, Endstruct, Init
};
/*
Types enum class
Assists in type checking in the parser function. For example, the
following values correspond to the following types:
1 Int
3.14 Double
"Hello!" String
'e' Char
true Bool
$value Value
&var Direct
%10 Line
See also parser function
*/
enum class Types {
Int, Double, String, Char, Bool, Value, Direct, Line, List, Label, Type, Function, Other
};
// Forward declaration of Literal for list
struct Literal;
/*
List struct
Contains literal values inside a vector. For example, if the following
program was written:
setlist #myNums 3 5 9 13
The List struct which would be created and stored should look like this:
{
val = {
Literal {
val = 3
},
Literal {
val = 5
},
Literal {
val = 9
},
Literal {
val = 13
},
}
}
All elements in the list must be of the same type. See also Literal struct.
*/
struct List {
std::vector<Literal> val;
};
/*
Direct struct
If the program being executed makes a direct reference, it is stored in a Direct
struct. For example, if the following line was written:
stdin &myVar
The Direct struct in the instruction should look like this:
{
varName = "myVar";
}
*/
struct Direct {
std::string varName;
};
struct TypeRef {
bool isCustomType = false;
std::string customType;
Types type;
};
struct FunctionRef {
std::string fnName;
};
/*
Label struct
Contains information needed to register labels
*/
struct Label {
std::string id;
int lineNum = -1;
};
/*
Line struct
Contains information needed to jump to lines
*/
struct Line {
int lineNum = -1;
bool isLabel = false;
std::string label;
};
/*
ValueRef struct
If the program being executed makes a value reference, it is stored in a ValueRef
struct. For example, if the following line was written:
stdin &myVar
The ValueRef struct in the instruction should look like this:
{
varName = "myVar";
}
*/
struct ValueRef {
std::string varName;
};
/*
Instruction struct
An instruction usually corresponds to a line in the program being interpreted.
For example, if the following line was written:
add 5 $myVar &outVar
The instruction should look like this:
{
inst = Instructions::Add;
args = {
Literal {
val = 5
},
ValueRef {
varName = "myVar"
},
Direct {
varName = "outVar"
}
};
}
inst starts as empty, so empty lines and commented out lines do not get in the
way of jump and if.
See also: Instructions enum class, Literal struct, ValueRef struct, Direct struct,
Line struct, exec function, parser function
*/
typedef std::variant<Literal, ValueRef, FunctionRef, TypeRef, Direct, Line> argument;
struct Instruction {
Instructions inst = Instructions::Empty;
std::vector<argument> args;
bool isLabel = false;
Label label;
};
struct FnArg {
Direct ref;
Types type;
};
/*
Function struct
Contains information needed to run a Ground function.
*/
struct Function {
Types returnType;
std::vector<FnArg> args;
std::vector<Instruction> instructions;
std::vector<Label> labels;
};
/*
Struct struct
This struct stores data for structures in Ground.
*/
struct Struct {
std::map<std::string, Literal> values;
std::map<std::string, Function> functions;
};
struct Error {
std::string code;
int pops;
std::string reporter;
};
/*
Literal struct
Contains literal values. For example, if the following line was written:
stdout "Hello world!"
The Literal struct in the instruction should look like this:
{
val = "Hello world!"; // I am ignoring the variant for simplicity
// of documenting the code
}
All value references are swapped out for their respective Literal they
point to. See also variables map, parser function, interpreter function
*/
struct Literal {
std::variant<int, double, bool, std::string, char, List, Struct, Error> val;
};
// C-compatible enum and types for developing libraries for Ground in C
typedef enum {
GROUND_INT,
GROUND_DOUBLE,
GROUND_BOOL,
GROUND_STRING,
GROUND_CHAR
} GroundType;
typedef struct {
GroundType type;
union {
int int_val;
double double_val;
int bool_val;
char* string_val;
char char_val;
} data;
} GroundValue;

184
src/parser/parser.cpp Normal file
View File

@@ -0,0 +1,184 @@
#include <vector>
#include <string>
#include <map>
#include "parser.h"
#include "../main.h"
#include "../data/data.h"
#include "../error/error.h"
using namespace std;
/*
parser function
This function takes a vector of a vector of strings from the lexer and
converts it into a list of instructions that the interpreter can understand.
*/
vector<Instruction> parser(vector<vector<string>> in) {
vector<Instruction> out;
for (vector<string> line : in) {
Instruction currentInstruction;
if (line.size() < 1) {
out.push_back(currentInstruction);
continue;
}
string inst = line[0];
if (isLabel(inst)) {
currentInstruction.isLabel = true;
currentInstruction.label.id = inst.substr(1);
line.erase(line.begin());
}
else if (isFunction(inst)) {
currentInstruction.inst = Instructions::Call;
FunctionRef newFnRef;
newFnRef.fnName = inst.substr(1);
currentInstruction.args.push_back(newFnRef);
}
else if (inst == "stdout") currentInstruction.inst = Instructions::Stdout;
else if (inst == "print") currentInstruction.inst = Instructions::Stdout;
else if (inst == "stdlnout") currentInstruction.inst = Instructions::Stdlnout;
else if (inst == "println") currentInstruction.inst = Instructions::Stdlnout;
else if (inst == "stdin") currentInstruction.inst = Instructions::Stdin;
else if (inst == "input") currentInstruction.inst = Instructions::Stdin;
else if (inst == "add") currentInstruction.inst = Instructions::Add;
else if (inst == "subtract") currentInstruction.inst = Instructions::Subtract;
else if (inst == "multiply") currentInstruction.inst = Instructions::Multiply;
else if (inst == "divide") currentInstruction.inst = Instructions::Divide;
else if (inst == "set") currentInstruction.inst = Instructions::Set;
else if (inst == "end") currentInstruction.inst = Instructions::End;
else if (inst == "jump") currentInstruction.inst = Instructions::Jump;
else if (inst == "if") currentInstruction.inst = Instructions::If;
else if (inst == "equal") currentInstruction.inst = Instructions::Equal;
else if (inst == "inequal") currentInstruction.inst = Instructions::Inequal;
else if (inst == "greater") currentInstruction.inst = Instructions::Greater;
else if (inst == "lesser") currentInstruction.inst = Instructions::Lesser;
else if (inst == "not") currentInstruction.inst = Instructions::Not;
else if (inst == "setlist") currentInstruction.inst = Instructions::Setlist;
else if (inst == "getlistat") currentInstruction.inst = Instructions::Getlistat;
else if (inst == "setlistat") currentInstruction.inst = Instructions::Setlistat;
else if (inst == "getlistsize") currentInstruction.inst = Instructions::Getlistsize;
else if (inst == "stoi") currentInstruction.inst = Instructions::Stoi;
else if (inst == "stod") currentInstruction.inst = Instructions::Stod;
else if (inst == "tostring") currentInstruction.inst = Instructions::Tostring;
else if (inst == "fun") currentInstruction.inst = Instructions::Fun;
else if (inst == "return") currentInstruction.inst = Instructions::Return;
else if (inst == "endfun") currentInstruction.inst = Instructions::Endfun;
else if (inst == "pusharg") currentInstruction.inst = Instructions::Pusharg;
else if (inst == "call") currentInstruction.inst = Instructions::Call;
else if (inst == "use") currentInstruction.inst = Instructions::Use;
else if (inst == "extern") currentInstruction.inst = Instructions::Extern;
else if (inst == "getstrcharat") currentInstruction.inst = Instructions::Getstrcharat;
else if (inst == "getstrsize") currentInstruction.inst = Instructions::Getstrsize;
else if (inst == "error") currentInstruction.inst = Instructions::Error;
else if (inst == "catch") currentInstruction.inst = Instructions::Catch;
else if (inst == "try") currentInstruction.inst = Instructions::Try;
else if (inst == "exception") currentInstruction.inst = Instructions::Exception;
else if (inst == "gettype") currentInstruction.inst = Instructions::Gettype;
else if (inst == "exists") currentInstruction.inst = Instructions::Exists;
else if (inst == "listappend") currentInstruction.inst = Instructions::Listappend;
else if (inst == "listprepend") currentInstruction.inst = Instructions::Listprepend;
else if (inst == "struct") currentInstruction.inst = Instructions::Struct;
else if (inst == "endstruct") currentInstruction.inst = Instructions::Endstruct;
else if (inst == "init") currentInstruction.inst = Instructions::Init;
else {
error("Unknown instruction " + inst);
}
for (int i = 1; i < line.size(); i++) {
string arg = line[i];
Types type = getType(arg);
switch (type) {
case Types::Int:
{
Literal newLit;
newLit.val = stoi(arg);
currentInstruction.args.push_back(newLit);
}
break;
case Types::Double:
{
Literal newLit;
newLit.val = stod(arg);
currentInstruction.args.push_back(newLit);
}
break;
case Types::String:
{
Literal newLit;
newLit.val = arg.substr(1, arg.size() - 2);
currentInstruction.args.push_back(newLit);
}
break;
case Types::Char:
{
Literal newLit;
newLit.val = arg[1];
currentInstruction.args.push_back(newLit);
}
break;
case Types::Bool:
{
Literal newLit;
if (arg == "true") newLit.val = true;
else newLit.val = false;
currentInstruction.args.push_back(newLit);
}
break;
case Types::Value:
{
ValueRef newVal;
newVal.varName = arg.substr(1);
currentInstruction.args.push_back(newVal);
}
break;
case Types::Direct:
{
Direct newDir;
newDir.varName = arg.substr(1);
currentInstruction.args.push_back(newDir);
}
break;
case Types::Line:
{
Line newLine;
string lineRef = arg.substr(1);
if (isInt(lineRef)) {
newLine.lineNum = stoi(lineRef);
} else {
newLine.isLabel = true;
newLine.label = lineRef;
}
currentInstruction.args.push_back(newLine);
}
break;
case Types::Type:
{
TypeRef newTypeRef;
string type = arg.substr(1);
if (type == "int") newTypeRef.type = Types::Int;
else if (type == "double") newTypeRef.type = Types::Double;
else if (type == "string") newTypeRef.type = Types::String;
else if (type == "char") newTypeRef.type = Types::Char;
else if (type == "bool") newTypeRef.type = Types::Bool;
else if (type == "list") newTypeRef.type = Types::List;
else {
newTypeRef.isCustomType = true;
newTypeRef.customType = type;
};
currentInstruction.args.push_back(newTypeRef);
}
break;
case Types::Function:
{
FunctionRef newFuncRef;
newFuncRef.fnName = arg.substr(1);
currentInstruction.args.push_back(newFuncRef);
}
break;
default:
error("Could not parse argument " + arg);
}
}
out.push_back(currentInstruction);
}
return out;
}

7
src/parser/parser.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <vector>
#include <string>
#include "../main.h"
std::vector<Instruction> parser(std::vector<std::vector<std::string>> in);

View File

@@ -1,11 +1,11 @@
#!/usr/bin/env ground
stdlnout "Program args: "
getlistsize *args &argsSize
getlistsize &args &argsSize
set &counter 0
@loopstart
equal $counter $argsSize &bool
if $bool %end
getlistat *args $counter &item
getlistat &args $counter &item
stdlnout $item
add 1 $counter &counter
jump %loopstart

View File

@@ -20,19 +20,19 @@ stdlnout $testVar
# Lists
setlist *testList "Item 1" "Another Item" "Item the Third"
getlistat *testList 2 &tmp
setlist &testList "Item 1" "Another Item" "Item the Third"
getlistat &testList 2 &tmp
stdlnout $tmp
setlistat *testList 1 "I changed this item"
getlistat *testList 1 &tmp
setlistat &testList 1 "I changed this item"
getlistat &testList 1 &tmp
stdlnout $tmp
listappend *testList "I appended this item"
getlistat *testList 3 &tmp
listappend &testList "I appended this item"
getlistat &testList 3 &tmp
stdlnout $tmp
getlistsize *testList &tmp
getlistsize &testList &tmp
stdlnout $tmp
# String Operations

View File

@@ -2,8 +2,8 @@ set &testVar "dingus"
exists &testVar &exist
stdlnout $exist
setlist *myList "item"
exists *myList &exist
setlist &myList "item"
exists &myList &exist
stdlnout $exist
@dingus
@@ -13,8 +13,5 @@ stdlnout $exist
exists &doesNotExist &exist
stdlnout $exist
exists *doesNotExist &exist
stdlnout $exist
exists %doesNotExist &exist
stdlnout $exist

View File

@@ -22,18 +22,18 @@ stdlnout "I called a function"
fun -list !dingus
stdlnout "Testing lists in functions"
setlist *dingle "heheheha" "hahahahe" "hmmm"
return *dingle
setlist &dingle "heheheha" "hahahahe" "hmmm"
return $dingle
endfun
call !dingus *outlist
call !dingus &outlist
getlistsize *outlist &size
getlistsize &outlist &size
set &counter 0
@loopstart
equal $size $counter &cond
if $cond %loopend
getlistat *outlist $counter &tmp
getlistat &outlist $counter &tmp
stdlnout $tmp
add 1 $counter &counter
jump %loopstart

View File

@@ -1,14 +1,14 @@
# A cool list
setlist *favWords "hello" "there" "general" "kenobi"
setlist &favWords "hello" "there" "general" "kenobi"
stdlnout $favWords
set &count 0
set &passedThrough true
@jmpbck
getlistat *favWords $count &tmp
getlistat &favWords $count &tmp
stdlnout $tmp
add $count 1 &count
getlistsize *favWords &tmp2
getlistsize &favWords &tmp2
inequal $count $tmp2 &tmp3
if $tmp3 %jmpbck