Parser is now working, just need functionality.
Added error output and line numbers. Next up: Proper functionality.
parent
048b26ca2b
commit
88bd82b762
145
src/lang.cc
145
src/lang.cc
|
@ -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;
|
||||
}
|
||||
|
|
18
src/lang.h
18
src/lang.h
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue