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" #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) { int read_file(std::deque<std::string> args) {
if (args.empty()) { if (args.empty()) {
std::cout << bg_red(bold("ERROR")) << ": No file input" << std::endl; return ferr("%s: No file input.\n", bg_red(bold("ERROR")).c_str());
return 1;
} }
fs::path filename = args[0]; filename = args[0];
args.pop_front(); args.pop_front();
std::ifstream file(filename); std::ifstream file(filename);
if (!file) { if (!file) {
std::cout << bg_red(bold("ERROR")) << ": Could not find file" << std::endl; return ferr("%s: Could not find file.\n", bg_red(bold("ERROR")).c_str());
return 1;
} }
std::string line; std::string line;
int row = 1;
while (std::getline(file, line)) { while (std::getline(file, line)) {
std::cout << line << std::endl; int error = parse_line(line, row);
if (error)
return 1;
row++;
} }
return 0; return 0;
} }
int parse_line(std::string line) { int parse_line(std::string line, int row) {
int col = 1;
struct parsed_token parsed { struct parsed_token parsed {
empty_token, empty_token empty_token, empty_token
}; };
if (int sub = line.find("//")) if (line.length() == 0)
line = line.substr(sub); return 0;
std::deque<std::string> tokens; std::deque<std::string> tokens;
int start = 0; int start = 0;
size_t end = line.find(" "); size_t end = line.find(" ");
@ -34,30 +51,106 @@ int parse_line(std::string line) {
end = line.find(" ", start); end = line.find(" ", start);
} }
for (std::string &token : tokens) { for (std::string &token : tokens) {
if (token == "//")
return 0;
const char *ctoken = token.c_str();
try { try {
Token curr_token = CV_Tokens.at(token); Token curr_token = CV_Tokens.at(token);
parsed.lastToken = parsed.currentToken; parsed.last_token = parsed.current_token;
if (curr_token == parsed.lastToken && curr_token.type == TokenType::SPACE) if (curr_token == parsed.last_token &&
curr_token.type == TokenType::SPACE)
continue; continue;
else { parsed.current_token = curr_token;
// TODO: Line number handling for better errors switch (parsed.current_token.type) {
std::cerr << "Invalid token `" << token << "'." << std::endl; case TokenType::COLONCOLON: {
return 1; 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) { } catch (std::out_of_range &oor) {
// this is most likely a variable or a string // this is most likely a variable or a string
if (parsed.lastToken.type == TokenType::INTRINSIC && ferr("%s: Invalid token `%s'.\n", here(row, col), ctoken);
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;
} }
col += token.length() + 1;
} }
return 0; return 0;
} }

View File

@ -1,14 +1,15 @@
#pragma once #pragma once
#include "colors.h" #include "colors.h"
#include <cstdarg>
#include <deque> #include <deque>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <map>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -27,7 +28,7 @@ enum class TokenType {
VARIABLE 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 }; 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::EMPTY, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{" ", Token{TokenType::SPACE, 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::COLONCOLON, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{"=", Token{TokenType::EQ, Intrinsic::EMPTY, Constant::EMPTY, "", ""}}, {"=", Token{TokenType::EQ, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{",", Token{TokenType::COMMA, Intrinsic::EMPTY, Constant::EMPTY, "", ""}}, {",", Token{TokenType::COMMA, Intrinsic::EMPTY, Constant::EMPTY, "", ""}},
{"%include",
Token{TokenType::INTRINSIC, Intrinsic::INCLUDE, Constant::EMPTY, "", ""}},
{"let", {"let",
Token{TokenType::INTRINSIC, Intrinsic::LET, Constant::EMPTY, "", ""}}, Token{TokenType::INTRINSIC, Intrinsic::LET, Constant::EMPTY, "", ""}},
{"unlet", {"unlet",
@ -92,11 +95,14 @@ std::map<std::string, Token> CV_Tokens{
Token empty_token{TokenType::EMPTY, Intrinsic::EMPTY, Constant::EMPTY, "", ""}; Token empty_token{TokenType::EMPTY, Intrinsic::EMPTY, Constant::EMPTY, "", ""};
struct parsed_token { struct parsed_token {
Token lastToken; Token last_token;
Token currentToken; Token current_token;
}; };
std::vector<VariableToken> var_tokens; 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 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) { int main(int argc, char **argv) {
if (argc != 2) { if (argc != 2) {
std::cout << "Wrong amount of args" << std::endl;
return 1; return 1;
} }
std::deque<std::string> args; std::deque<std::string> args;
args.push_back(std::string(argv[1])); args.push_back(std::string(argv[1]));
return read_file(args); return read_file(args);
return 0;
} }