forked from ground/ground
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			81d6e21a00
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e5a39f07fb | |||
| fa5d805eef | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,3 @@
 | 
				
			|||||||
ground
 | 
					ground
 | 
				
			||||||
Bobfile
 | 
					Bobfile
 | 
				
			||||||
 | 
					build
 | 
				
			||||||
							
								
								
									
										5
									
								
								Bobfile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Bobfile
									
									
									
									
									
								
							@@ -1,5 +0,0 @@
 | 
				
			|||||||
compiler "g++";
 | 
					 | 
				
			||||||
binary "ground";
 | 
					 | 
				
			||||||
source "src/main.cpp";
 | 
					 | 
				
			||||||
flag "Ofast";
 | 
					 | 
				
			||||||
compile;
 | 
					 | 
				
			||||||
							
								
								
									
										22
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Makefile
									
									
									
									
									
										Normal 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
 | 
				
			||||||
@@ -13,13 +13,7 @@ Ground is an interpreter which processes and interprets Ground instructions. It
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## How do I get started?
 | 
					## How do I get started?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Clone the repo and compile with your favourite C++ compiler:
 | 
					Clone the repo and compile with `make`.
 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
  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.)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Run a Ground program:
 | 
					Run a Ground program:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										244
									
								
								src/data/data.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								src/data/data.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										66
									
								
								src/data/data.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										34
									
								
								src/error/error.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										6
									
								
								src/error/error.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../main.h"
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Literal error(std::string in, std::string errCode = "syntaxError", int exitc = 1);
 | 
				
			||||||
							
								
								
									
										2003
									
								
								src/interpreter/interpreter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2003
									
								
								src/interpreter/interpreter.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										7
									
								
								src/interpreter/interpreter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/interpreter/interpreter.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										81
									
								
								src/lexer/lexer.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										6
									
								
								src/lexer/lexer.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::vector<std::vector<std::string>> lexer(std::string in);
 | 
				
			||||||
							
								
								
									
										2916
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										2916
									
								
								src/main.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										250
									
								
								src/main.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/main.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										184
									
								
								src/parser/parser.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										7
									
								
								src/parser/parser.h
									
									
									
									
									
										Normal 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);
 | 
				
			||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
#!/usr/bin/env ground
 | 
					#!/usr/bin/env ground
 | 
				
			||||||
stdlnout "Program args: "
 | 
					stdlnout "Program args: "
 | 
				
			||||||
getlistsize *args &argsSize
 | 
					getlistsize &args &argsSize
 | 
				
			||||||
set &counter 0
 | 
					set &counter 0
 | 
				
			||||||
@loopstart
 | 
					@loopstart
 | 
				
			||||||
equal $counter $argsSize &bool
 | 
					equal $counter $argsSize &bool
 | 
				
			||||||
if $bool %end
 | 
					if $bool %end
 | 
				
			||||||
getlistat *args $counter &item
 | 
					getlistat &args $counter &item
 | 
				
			||||||
stdlnout $item
 | 
					stdlnout $item
 | 
				
			||||||
add 1 $counter &counter
 | 
					add 1 $counter &counter
 | 
				
			||||||
jump %loopstart
 | 
					jump %loopstart
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,19 +20,19 @@ stdlnout $testVar
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Lists
 | 
					# Lists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
setlist *testList "Item 1" "Another Item" "Item the Third"
 | 
					setlist &testList "Item 1" "Another Item" "Item the Third"
 | 
				
			||||||
getlistat *testList 2 &tmp
 | 
					getlistat &testList 2 &tmp
 | 
				
			||||||
stdlnout $tmp
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
setlistat *testList 1 "I changed this item"
 | 
					setlistat &testList 1 "I changed this item"
 | 
				
			||||||
getlistat *testList 1 &tmp
 | 
					getlistat &testList 1 &tmp
 | 
				
			||||||
stdlnout $tmp
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
listappend *testList "I appended this item"
 | 
					listappend &testList "I appended this item"
 | 
				
			||||||
getlistat *testList 3 &tmp
 | 
					getlistat &testList 3 &tmp
 | 
				
			||||||
stdlnout $tmp
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
getlistsize *testList &tmp
 | 
					getlistsize &testList &tmp
 | 
				
			||||||
stdlnout $tmp
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# String Operations
 | 
					# String Operations
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,8 @@ set &testVar "dingus"
 | 
				
			|||||||
exists &testVar &exist
 | 
					exists &testVar &exist
 | 
				
			||||||
stdlnout $exist
 | 
					stdlnout $exist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
setlist *myList "item"
 | 
					setlist &myList "item"
 | 
				
			||||||
exists *myList &exist
 | 
					exists &myList &exist
 | 
				
			||||||
stdlnout $exist
 | 
					stdlnout $exist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@dingus
 | 
					@dingus
 | 
				
			||||||
@@ -13,8 +13,5 @@ stdlnout $exist
 | 
				
			|||||||
exists &doesNotExist &exist
 | 
					exists &doesNotExist &exist
 | 
				
			||||||
stdlnout $exist
 | 
					stdlnout $exist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exists *doesNotExist &exist
 | 
					 | 
				
			||||||
stdlnout $exist
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exists %doesNotExist &exist
 | 
					exists %doesNotExist &exist
 | 
				
			||||||
stdlnout $exist
 | 
					stdlnout $exist
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,18 +22,18 @@ stdlnout "I called a function"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
fun -list !dingus
 | 
					fun -list !dingus
 | 
				
			||||||
    stdlnout "Testing lists in functions"
 | 
					    stdlnout "Testing lists in functions"
 | 
				
			||||||
    setlist *dingle "heheheha" "hahahahe" "hmmm"
 | 
					    setlist &dingle "heheheha" "hahahahe" "hmmm"
 | 
				
			||||||
    return *dingle
 | 
					    return $dingle
 | 
				
			||||||
endfun
 | 
					endfun
 | 
				
			||||||
 | 
					
 | 
				
			||||||
call !dingus *outlist
 | 
					call !dingus &outlist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
getlistsize *outlist &size
 | 
					getlistsize &outlist &size
 | 
				
			||||||
set &counter 0
 | 
					set &counter 0
 | 
				
			||||||
@loopstart
 | 
					@loopstart
 | 
				
			||||||
equal $size $counter &cond
 | 
					equal $size $counter &cond
 | 
				
			||||||
if $cond %loopend
 | 
					if $cond %loopend
 | 
				
			||||||
getlistat *outlist $counter &tmp
 | 
					getlistat &outlist $counter &tmp
 | 
				
			||||||
stdlnout $tmp
 | 
					stdlnout $tmp
 | 
				
			||||||
add 1 $counter &counter
 | 
					add 1 $counter &counter
 | 
				
			||||||
jump %loopstart
 | 
					jump %loopstart
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,14 @@
 | 
				
			|||||||
# A cool list
 | 
					# A cool list
 | 
				
			||||||
setlist *favWords "hello" "there" "general" "kenobi"
 | 
					setlist &favWords "hello" "there" "general" "kenobi"
 | 
				
			||||||
stdlnout $favWords
 | 
					stdlnout $favWords
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set &count 0
 | 
					set &count 0
 | 
				
			||||||
set &passedThrough true
 | 
					set &passedThrough true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@jmpbck
 | 
					@jmpbck
 | 
				
			||||||
getlistat *favWords $count &tmp
 | 
					getlistat &favWords $count &tmp
 | 
				
			||||||
stdlnout $tmp
 | 
					stdlnout $tmp
 | 
				
			||||||
add $count 1 &count
 | 
					add $count 1 &count
 | 
				
			||||||
getlistsize *favWords &tmp2
 | 
					getlistsize &favWords &tmp2
 | 
				
			||||||
inequal $count $tmp2 &tmp3
 | 
					inequal $count $tmp2 &tmp3
 | 
				
			||||||
if $tmp3 %jmpbck
 | 
					if $tmp3 %jmpbck
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user