2025-09-30 21:29:06 +10:00
|
|
|
#include "parser.h"
|
|
|
|
|
#include "../error/error.h"
|
2025-10-04 11:50:46 +10:00
|
|
|
#include "../utils/trim/trim.h"
|
2025-09-30 21:29:06 +10:00
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
std::vector<Instruction> parse(std::string program) {
|
|
|
|
|
std::vector<Instruction> instructions;
|
|
|
|
|
std::vector<std::string> lines;
|
|
|
|
|
std::string buf;
|
|
|
|
|
int blockTracker = 0;
|
|
|
|
|
|
|
|
|
|
for (char chr : program) {
|
|
|
|
|
if (chr == '{') {
|
|
|
|
|
blockTracker++;
|
|
|
|
|
} else if (chr == '}') {
|
|
|
|
|
if (blockTracker > 0) {
|
|
|
|
|
blockTracker--;
|
|
|
|
|
} else {
|
|
|
|
|
error("Expected opening '{' to match closing '}'");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((chr == '\n' || chr == ';') && blockTracker == 0) {
|
|
|
|
|
if (!buf.empty()) {
|
|
|
|
|
lines.push_back(buf);
|
|
|
|
|
buf.clear();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
buf.push_back(chr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (blockTracker != 0) {
|
|
|
|
|
error("Expected closing '}' to match opening '{'");
|
|
|
|
|
}
|
|
|
|
|
if (!buf.empty()) {
|
|
|
|
|
lines.push_back(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (std::string line : lines) {
|
|
|
|
|
line = trim(line);
|
|
|
|
|
if (line.empty()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-04 12:08:57 +10:00
|
|
|
// Ignore commented lines
|
|
|
|
|
if (line[0] == '#') {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-30 21:29:06 +10:00
|
|
|
if (line.rfind("if", 0) == 0) {
|
|
|
|
|
Instruction if_inst;
|
|
|
|
|
if_inst.instruction = InstructionType::If;
|
|
|
|
|
|
|
|
|
|
size_t block_start = line.find('{');
|
|
|
|
|
if (block_start == std::string::npos) {
|
|
|
|
|
error("Expected '{' for if statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1. Condition
|
|
|
|
|
std::string condition_str = line.substr(2, block_start - 2);
|
|
|
|
|
if_inst.args.push_back(Value(Instruction(split(trim(condition_str)))));
|
|
|
|
|
|
|
|
|
|
// 2. Find 'then' block
|
|
|
|
|
size_t block_end = 0;
|
|
|
|
|
int brace_level = 0;
|
|
|
|
|
for (size_t i = block_start; i < line.length(); ++i) {
|
|
|
|
|
if (line[i] == '{') brace_level++;
|
|
|
|
|
else if (line[i] == '}') brace_level--;
|
|
|
|
|
if (brace_level == 0) {
|
|
|
|
|
block_end = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (block_end == 0) {
|
|
|
|
|
error("Mismatched braces in if statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
|
|
|
|
if_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
|
|
|
|
|
|
|
|
|
// 3. Else block (optional)
|
|
|
|
|
std::string remaining_line = trim(line.substr(block_end + 1));
|
|
|
|
|
if (remaining_line.rfind("else", 0) == 0) {
|
|
|
|
|
size_t else_block_start = remaining_line.find('{');
|
|
|
|
|
if (else_block_start == std::string::npos) {
|
|
|
|
|
error("Expected '{' for else statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
size_t else_block_end = remaining_line.find_last_of('}');
|
|
|
|
|
if (else_block_end == std::string::npos) {
|
|
|
|
|
error("Expected '}' for else statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::string else_content = remaining_line.substr(else_block_start + 1, else_block_end - else_block_start - 1);
|
|
|
|
|
if_inst.args.push_back(Value(parse(else_content)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
instructions.push_back(if_inst);
|
|
|
|
|
} else if (line.rfind("while", 0) == 0) {
|
|
|
|
|
Instruction while_inst;
|
|
|
|
|
while_inst.instruction = InstructionType::While;
|
|
|
|
|
|
|
|
|
|
size_t block_start = line.find('{');
|
|
|
|
|
if (block_start == std::string::npos) {
|
|
|
|
|
error("Expected '{' for while statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1. Condition
|
|
|
|
|
std::string condition_str = line.substr(5, block_start - 5);
|
|
|
|
|
while_inst.args.push_back(Value(Instruction(split(trim(condition_str)))));
|
|
|
|
|
|
|
|
|
|
// 2. Find 'then' block
|
|
|
|
|
size_t block_end = 0;
|
|
|
|
|
int brace_level = 0;
|
|
|
|
|
for (size_t i = block_start; i < line.length(); ++i) {
|
|
|
|
|
if (line[i] == '{') brace_level++;
|
|
|
|
|
else if (line[i] == '}') brace_level--;
|
|
|
|
|
if (brace_level == 0) {
|
|
|
|
|
block_end = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (block_end == 0) {
|
|
|
|
|
error("Mismatched braces in while statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
|
|
|
|
while_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
|
|
|
|
instructions.push_back(while_inst);
|
2025-10-01 13:43:08 +10:00
|
|
|
} else if (line.rfind("fun", 0) == 0) {
|
|
|
|
|
Instruction function_inst;
|
|
|
|
|
function_inst.instruction = InstructionType::Function;
|
|
|
|
|
|
|
|
|
|
size_t block_start = line.find('{');
|
|
|
|
|
if (block_start == std::string::npos) {
|
|
|
|
|
error("Expected '{' for function statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-02 12:41:11 +10:00
|
|
|
// 1. Function signature (name + args)
|
|
|
|
|
std::string signature_str = line.substr(3, block_start - 3);
|
|
|
|
|
std::vector<Value> signature_parts = split(trim(signature_str));
|
|
|
|
|
|
|
|
|
|
if (signature_parts.empty()) {
|
|
|
|
|
error("Function definition is missing a name.");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(const auto& part : signature_parts) {
|
|
|
|
|
function_inst.args.push_back(part);
|
|
|
|
|
}
|
2025-10-01 13:43:08 +10:00
|
|
|
|
|
|
|
|
// 2. Find 'then' block
|
|
|
|
|
size_t block_end = 0;
|
|
|
|
|
int brace_level = 0;
|
|
|
|
|
for (size_t i = block_start; i < line.length(); ++i) {
|
|
|
|
|
if (line[i] == '{') brace_level++;
|
|
|
|
|
else if (line[i] == '}') brace_level--;
|
|
|
|
|
if (brace_level == 0) {
|
|
|
|
|
block_end = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (block_end == 0) {
|
|
|
|
|
error("Mismatched braces in function statement");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
|
|
|
|
function_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
|
|
|
|
instructions.push_back(function_inst);
|
2025-09-30 21:29:06 +10:00
|
|
|
} else {
|
|
|
|
|
instructions.push_back(Instruction(split(line)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return instructions;
|
2025-10-01 13:43:08 +10:00
|
|
|
}
|