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"
|
#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;
|
||||||
}
|
}
|
||||||
|
|
18
src/lang.h
18
src/lang.h
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue