2024-06-06 13:37:13 +02:00
|
|
|
#include "parser.hpp"
|
|
|
|
|
#include "ast/function.hpp"
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
blitz::parser::parser(std::string file) {
|
2024-06-06 13:37:13 +02:00
|
|
|
// Try and load the file
|
|
|
|
|
std::shared_ptr<std::ifstream> instream = std::make_shared<std::ifstream>(file);
|
|
|
|
|
if (instream->bad() || !instream->good()) {
|
|
|
|
|
throw std::ios_base::failure("Failed to open file.");
|
|
|
|
|
}
|
|
|
|
|
m_files.push(std::make_pair(file, instream));
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
blitz::parser::~parser() {
|
2024-06-06 13:37:13 +02:00
|
|
|
while (m_files.size() > 0) {
|
|
|
|
|
std::shared_ptr<std::ifstream> file = std::dynamic_pointer_cast<std::ifstream>(m_files.top().second);
|
|
|
|
|
file->close();
|
|
|
|
|
m_files.pop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
std::unique_ptr<blitz::AST::Expression> blitz::parser::Parse() {
|
2024-06-06 13:37:13 +02:00
|
|
|
std::unique_ptr<AST::ScopeExpression> scope = std::make_unique<AST::ScopeExpression>();
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<AST::Expression> expr;
|
2024-06-06 14:04:34 +02:00
|
|
|
while ((expr = std::move(parse_expression())) != nullptr) {
|
2024-06-06 13:37:13 +02:00
|
|
|
scope->AddExpression(std::move(expr));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::move(scope);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
void blitz::parser::LogMessage(const char* msg, ...) {
|
2024-06-06 13:37:13 +02:00
|
|
|
std::vector<char> buf(65535);
|
|
|
|
|
va_list val;
|
|
|
|
|
va_start(val, msg);
|
|
|
|
|
int rval = vsnprintf(buf.data(), buf.size(), msg, val);
|
|
|
|
|
va_end(val);
|
|
|
|
|
std::cout << buf.data() << '\n';
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
void blitz::parser::LogError(const char* msg, ...) {
|
2024-06-06 13:37:13 +02:00
|
|
|
std::vector<char> buf(65535);
|
|
|
|
|
va_list val;
|
|
|
|
|
va_start(val, msg);
|
|
|
|
|
int rval = vsnprintf(buf.data(), buf.size(), msg, val);
|
|
|
|
|
va_end(val);
|
|
|
|
|
std::cerr << buf.data() << '\n';
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
std::pair<blitz::Lexer::Token, std::string> blitz::parser::GetNextToken() {
|
2024-06-06 13:37:13 +02:00
|
|
|
return m_lexer.GetNextToken(m_files.top().second);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
std::unique_ptr<blitz::AST::Expression> blitz::parser::parse_expression() {
|
2024-06-06 13:37:13 +02:00
|
|
|
while (true) {
|
|
|
|
|
auto tkn = GetNextToken();
|
|
|
|
|
|
|
|
|
|
switch (tkn.first) {
|
2024-06-06 14:04:34 +02:00
|
|
|
case blitz::Lexer::Token::TokenNewLine:
|
|
|
|
|
case blitz::Lexer::Token::TokenComment:
|
2024-06-06 13:37:13 +02:00
|
|
|
// Skip Comments, since we don't really need them for the AST.
|
|
|
|
|
continue;
|
2024-06-06 14:04:34 +02:00
|
|
|
case blitz::Lexer::Token::TokenPlus:
|
|
|
|
|
case blitz::Lexer::Token::TokenMinus:
|
2024-06-06 13:37:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
default: // End Of File / Unknown
|
2024-06-06 14:04:34 +02:00
|
|
|
case blitz::Lexer::Token::TokenUnknown:
|
|
|
|
|
case blitz::Lexer::Token::TokenEOF:
|
2024-06-06 13:37:13 +02:00
|
|
|
return nullptr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
std::unique_ptr<blitz::AST::NumberExpression> blitz::parser::parse_number(blitz::Lexer::Token token, std::string value) {
|
2024-06-06 13:37:13 +02:00
|
|
|
if (token != Lexer::Token::TokenNumber) {
|
|
|
|
|
LogError("Unexpected Token during parsing, expected number.");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* endptr = const_cast<char*>(value.c_str() + value.size());
|
|
|
|
|
int32_t parsed = strtol(value.c_str(), &endptr, 10);
|
|
|
|
|
if (errno == ERANGE) {
|
|
|
|
|
LogError("Number out of range.");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
return std::make_unique<blitz::AST::NumberExpression>(parsed);
|
2024-06-06 13:37:13 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
std::unique_ptr<blitz::AST::DecimalExpression> blitz::parser::parse_decimal(blitz::Lexer::Token token, std::string value) {
|
2024-06-06 13:37:13 +02:00
|
|
|
if (token != Lexer::Token::TokenNumber) {
|
|
|
|
|
LogError("Unexpected Token during parsing, expected number.");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* endptr = const_cast<char*>(value.c_str() + value.size());
|
|
|
|
|
float_t parsed = strtof(value.c_str(), &endptr);
|
|
|
|
|
if (errno == ERANGE) {
|
|
|
|
|
LogError("Number out of range.");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-06 14:04:34 +02:00
|
|
|
return std::make_unique<blitz::AST::DecimalExpression>(parsed);
|
2024-06-06 13:37:13 +02:00
|
|
|
}
|