forked from ground/highground
Simple parsing and code generation
This commit is contained in:
175
src/main.cpp
175
src/main.cpp
@@ -1,3 +1,5 @@
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <groundvm.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -5,32 +7,193 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
namespace HighGround {
|
||||
|
||||
int tmpIdIterator = 0;
|
||||
|
||||
namespace Parser {
|
||||
|
||||
enum class HGNodeType {
|
||||
Add, Subtract, Equal, Set, While, If, None, Root, CodeBlock
|
||||
Add, Subtract, Equal, Set, While, If, Value, Identifier, None, Root, CodeBlock
|
||||
};
|
||||
|
||||
enum class HGDataType {
|
||||
Int, String, Double, Bool, Char, None
|
||||
};
|
||||
|
||||
class HGNode;
|
||||
|
||||
class HGGroundCodeBlock {
|
||||
public:
|
||||
std::vector<GroundInstruction> code;
|
||||
HGGroundCodeBlock() = default;
|
||||
};
|
||||
|
||||
class HGData {
|
||||
std::variant<int64_t, std::string, double, bool, char> data;
|
||||
public:
|
||||
HGDataType type = HGDataType::Int;
|
||||
HGData() = default;
|
||||
HGData(int64_t in) : data(in) {}
|
||||
std::optional<int64_t> getInt() {
|
||||
if (type == HGDataType::Int) {
|
||||
return std::get<int64_t>(data);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class HGNode {
|
||||
HGNodeType nodeType = HGNodeType::None;
|
||||
HGData data;
|
||||
std::vector<HGNode> children;
|
||||
public:
|
||||
std::string outputId;
|
||||
HGNode(HGNodeType nodeType) : nodeType(nodeType) {}
|
||||
HGNode(HGNodeType nodeType, HGData data) : nodeType(nodeType), data(data) {}
|
||||
HGNode() = default;
|
||||
void addNode(HGNode in) {
|
||||
children.push_back(in);
|
||||
}
|
||||
std::vector<GroundInstruction> generateCode() {
|
||||
std::vector<GroundInstruction> code;
|
||||
void setValue(HGData in) {
|
||||
data = in;
|
||||
}
|
||||
const std::vector<HGGroundCodeBlock> generateCode() {
|
||||
std::vector<HGGroundCodeBlock> code;
|
||||
for (auto& child : children) {
|
||||
auto childCode = child.generateCode();
|
||||
code.insert(code.end(), childCode.begin(), childCode.end());
|
||||
}
|
||||
switch (nodeType) {
|
||||
case HGNodeType::Value: {
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
HGGroundCodeBlock codeBlock;
|
||||
GroundInstruction gi = groundCreateInstruction(SET);
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
||||
switch (data.type) {
|
||||
case HGDataType::Int: {
|
||||
auto dataopt = data.getInt();
|
||||
if (dataopt) {
|
||||
groundAddValueToInstruction(&gi, groundCreateValue(INT, dataopt.value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
codeBlock.code.push_back(gi);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
std::cout << "Not implemented yet\n";
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Parser {
|
||||
std::vector<std::string> tokensToParse;
|
||||
size_t current;
|
||||
size_t size;
|
||||
|
||||
std::optional<std::string> peek(int ahead = 1) {
|
||||
if (current + ahead < size) {
|
||||
return tokensToParse[current + ahead];
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string> consume() {
|
||||
if (current < size) {
|
||||
return tokensToParse[current++];
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool isInt(std::string in) {
|
||||
for (const char& c : in) {
|
||||
if (!std::isdigit(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool isDouble(std::string in) {
|
||||
bool foundDot = false;
|
||||
for (const char& c : in) {
|
||||
if (!std::isdigit(c)) {
|
||||
if (!foundDot && c == '.') {
|
||||
foundDot = true;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HGDataType getDataType(std::string in) {
|
||||
if (isInt(in)) {
|
||||
return HGDataType::Int;
|
||||
}
|
||||
if (isDouble(in)) {
|
||||
return HGDataType::Double;
|
||||
}
|
||||
return HGDataType::None;
|
||||
}
|
||||
|
||||
HGNodeType getNodeType(std::string in) {
|
||||
if (getDataType(in) != HGDataType::None) {
|
||||
return HGNodeType::Value;
|
||||
}
|
||||
return HGNodeType::None;
|
||||
}
|
||||
|
||||
public:
|
||||
Parser(std::vector<std::string> in) : tokensToParse(in) {}
|
||||
|
||||
HGNode parse() {
|
||||
current = 0;
|
||||
size = tokensToParse.size();
|
||||
HGNode rootNode(HGNodeType::Root);
|
||||
while (auto tokenopt = consume()) {
|
||||
std::string token = tokenopt.value();
|
||||
switch (getNodeType(token)) {
|
||||
case HGNodeType::Value: {
|
||||
switch (getDataType(token)) {
|
||||
case HGDataType::Int: {
|
||||
std::cout << "We have an int\n";
|
||||
HGNode intNode(HGNodeType::Value);
|
||||
intNode.setValue(std::stoll(token));
|
||||
rootNode.addNode(intNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rootNode;
|
||||
}
|
||||
};
|
||||
|
||||
GroundProgram assembleProgram(HGNode& rootNode) {
|
||||
GroundProgram gp = groundCreateProgram();
|
||||
auto code = rootNode.generateCode();
|
||||
for (int i = 0; i < code.size(); i++) {
|
||||
for (const auto& inst : code[i].code) {
|
||||
groundAddInstructionToProgram(&gp, inst);
|
||||
}
|
||||
}
|
||||
groundAddInstructionToProgram(&gp, groundCreateInstruction(PAUSE));
|
||||
return gp;
|
||||
}
|
||||
|
||||
} // namespace Parser
|
||||
|
||||
class Lexer {
|
||||
@@ -156,7 +319,7 @@ int main(int argc, char** argv) {
|
||||
std::ostringstream ss;
|
||||
ss << file.rdbuf();
|
||||
auto lexed = HighGround::Lexer(ss.str()).lex();
|
||||
for (const std::string& str : lexed) {
|
||||
std::cout << str << "\n";
|
||||
}
|
||||
auto parsed = HighGround::Parser::Parser(lexed).parse();
|
||||
GroundProgram program = HighGround::Parser::assembleProgram(parsed);
|
||||
groundRunProgram(&program);
|
||||
}
|
||||
|
||||
1
tests/int.hg
Normal file
1
tests/int.hg
Normal file
@@ -0,0 +1 @@
|
||||
32 12 3320932 31920
|
||||
Reference in New Issue
Block a user