Files
kyn/src/parser/parser.cpp
2025-10-02 12:41:11 +10:00

188 lines
6.4 KiB
C++

#include "parser.h"
#include "../error/error.h"
#include <string>
#include <vector>
// Helper to trim whitespace
std::string trim(const std::string& str) {
size_t first = str.find_first_not_of(" \t\n\r");
if (std::string::npos == first) {
return str;
}
size_t last = str.find_last_not_of(" \t\n\r");
return str.substr(first, (last - first + 1));
}
std::vector<Instruction> parse(std::string program) {
std::vector<Instruction> 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;
}
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);
} 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;
}
// 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);
}
// 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);
} else {
instructions.push_back(Instruction(split(line)));
}
}
return instructions;
}