Parser is now working, just need functionality.

Added error output and line numbers. Next up: Proper functionality.
Ruben 2023-01-26 16:51:56 +01:00
parent 048b26ca2b
commit 88bd82b762
No known key found for this signature in database
GPG Key ID: F6DAAC2742760162
3 changed files with 133 additions and 32 deletions

View File

@ -1,30 +1,47 @@
#include "lang.h"
const char *here(int row, int col) {
char *ret = (char *)malloc(sizeof(char *));
std::sprintf(ret, "%s:%d:%d", filename.string().c_str(), row, col);
return ret;
}
int ferr(const char *fmt, ...) {
std::va_list va;
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
return 1;
}
int read_file(std::deque<std::string> args) {
if (args.empty()) {
std::cout << bg_red(bold("ERROR")) << ": No file input" << std::endl;
return 1;
return ferr("%s: No file input.\n", bg_red(bold("ERROR")).c_str());
}
fs::path filename = args[0];
filename = args[0];
args.pop_front();
std::ifstream file(filename);
if (!file) {
std::cout << bg_red(bold("ERROR")) << ": Could not find file" << std::endl;
return 1;
return ferr("%s: Could not find file.\n", bg_red(bold("ERROR")).c_str());
}
std::string line;
int row = 1;
while (std::getline(file, line)) {
std::cout << line << std::endl;
int error = parse_line(line, row);
if (error)
return 1;
row++;
}
return 0;
}
int parse_line(std::string line) {
int parse_line(std::string line, int row) {
int col = 1;
struct parsed_token parsed {
empty_token, empty_token
};
if (int sub = line.find("//"))
line = line.substr(sub);
if (line.length() == 0)
return 0;
std::deque<std::string> tokens;
int start = 0;
size_t end = line.find(" ");
@ -34,30 +51,106 @@ int parse_line(std::string line) {
end = line.find(" ", start);
}
for (std::string &token : tokens) {
if (token == "//")
return 0;
const char *ctoken = token.c_str();
try {
Token curr_token = CV_Tokens.at(token);
parsed.lastToken = parsed.currentToken;
if (curr_token == parsed.lastToken && curr_token.type == TokenType::SPACE)
parsed.last_token = parsed.current_token;
if (curr_token == parsed.last_token &&
curr_token.type == TokenType::SPACE)
continue;
else {
// TODO: Line number handling for better errors
std::cerr << "Invalid token `" << token << "'." << std::endl;
return 1;
parsed.current_token = curr_token;
switch (parsed.current_token.type) {
case TokenType::COLONCOLON: {
ferr("%s: Token `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case TokenType::COMMA: {
ferr("%s: Token `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case TokenType::EQ: {
ferr("%s: Token `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case TokenType::LEFT_PAREN: {
ferr("%s: Token `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case TokenType::RIGHT_PAREN: {
ferr("%s: Token `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
}
switch (parsed.current_token.intrinsic) {
case Intrinsic::INCLUDE: {
ferr("%s: Intrinsic `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Intrinsic::ENTER: {
ferr("%s: Intrinsic `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Intrinsic::EXIT: {
ferr("%s: Intrinsic `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Intrinsic::HIDE: {
ferr("%s: Intrinsic `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Intrinsic::LET: {
ferr("%s: Intrinsic `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Intrinsic::SHOW: {
ferr("%s: Intrinsic `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Intrinsic::UNLET: {
ferr("%s: Intrinsic `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
default:
break;
}
switch (parsed.current_token.constant) {
case Constant::CHARACTER: {
ferr("%s: Constant `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Constant::IMAGE: {
ferr("%s: Constant `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
case Constant::LOCATION: {
ferr("%s: Constant `%s' is not yet implemented.\n", here(row, col),
ctoken);
break;
}
default:
break;
}
parsed.currentToken = curr_token;
} catch (std::out_of_range &oor) {
// this is most likely a variable or a string
if (parsed.lastToken.type == TokenType::INTRINSIC &&
parsed.lastToken.intrinsic == Intrinsic::LET) {
VariableToken var{TokenType::VARIABLE, Intrinsic::EMPTY,
Constant::EMPTY, "", token};
parsed.currentToken = var;
var_tokens.push_back(var);
}
// string parsing
std::cerr << "Not implemented. Found `" << token << "'." << std::endl;
continue;
ferr("%s: Invalid token `%s'.\n", here(row, col), ctoken);
}
col += token.length() + 1;
}
return 0;
}

View File

@ -1,14 +1,15 @@
#pragma once
#include "colors.h"
#include <cstdarg>
#include <deque>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
namespace fs = std::filesystem;
@ -27,7 +28,7 @@ enum class TokenType {
VARIABLE
};
enum class Intrinsic { EMPTY, LET, UNLET, ENTER, EXIT, SHOW, HIDE };
enum class Intrinsic { INCLUDE, EMPTY, LET, UNLET, ENTER, EXIT, SHOW, HIDE };
enum class Constant { EMPTY, CHARACTER, LOCATION, IMAGE };
@ -59,7 +60,7 @@ struct VariableToken : Token {
}
};
std::map<std::string, Token> CV_Tokens{
std::unordered_map<std::string, Token> CV_Tokens{
{"", Token{TokenType::EMPTY, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{" ", Token{TokenType::SPACE, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{"(",
@ -70,6 +71,8 @@ std::map<std::string, Token> CV_Tokens{
Token{TokenType::COLONCOLON, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{"=", Token{TokenType::EQ, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{",", Token{TokenType::COMMA, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{"%include",
Token{TokenType::INTRINSIC, Intrinsic::INCLUDE, Constant::EMPTY, "", ""}},
{"let",
Token{TokenType::INTRINSIC, Intrinsic::LET, Constant::EMPTY, "", ""}},
{"unlet",
@ -92,11 +95,14 @@ std::map<std::string, Token> CV_Tokens{
Token empty_token{TokenType::EMPTY, Intrinsic::EMPTY, Constant::EMPTY, "", ""};
struct parsed_token {
Token lastToken;
Token currentToken;
Token last_token;
Token current_token;
};
std::vector<VariableToken> var_tokens;
fs::path filename;
const char *here(int row, int col);
int ferr(std::string fmt, ...);
int read_file(std::deque<std::string> args);
int parse_line(std::string line);
int parse_line(std::string line, int row);

View File

@ -4,9 +4,11 @@
int main(int argc, char **argv) {
if (argc != 2) {
std::cout << "Wrong amount of args" << std::endl;
return 1;
}
std::deque<std::string> args;
args.push_back(std::string(argv[1]));
return read_file(args);
return 0;
}