put the impl in the cpp file for Parser
This commit is contained in:
parent
b6309de7a2
commit
e2ee2b130e
2 changed files with 135 additions and 118 deletions
120
src/parser.cpp
120
src/parser.cpp
|
|
@ -70,3 +70,123 @@ Expression *Parser::parse(vector<Token> tokenlist) {
|
||||||
current_token = 0;
|
current_token = 0;
|
||||||
return expression();
|
return expression();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token Parser::peek() { return tokens[current_token]; };
|
||||||
|
|
||||||
|
bool Parser::is_at_end() { return peek().tokentype == Token::END_OF_FILE; };
|
||||||
|
|
||||||
|
Token *Parser::previous() { return &tokens[current_token - 1]; };
|
||||||
|
|
||||||
|
Token *Parser::advance() {
|
||||||
|
if (!is_at_end())
|
||||||
|
current_token += 1;
|
||||||
|
return previous();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::check(Token::Type type) {
|
||||||
|
if (is_at_end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return peek().tokentype == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::match(int count, ...) {
|
||||||
|
va_list list;
|
||||||
|
va_start(list, count);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
Token::Type ttc = va_arg(list, Token::Type);
|
||||||
|
// cout << token_name(ttc) << "\n";
|
||||||
|
if (check(ttc)) {
|
||||||
|
advance();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Token *Parser::consume(Token::Type typ, string message) {
|
||||||
|
if (check(typ)) {
|
||||||
|
return advance();
|
||||||
|
}
|
||||||
|
throw error(peek(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_error Parser::error(Token token, string message) {
|
||||||
|
cout << token.as_string() << " " << message;
|
||||||
|
return runtime_error(message); // TODO no exceptions
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *Parser::primary() {
|
||||||
|
if (match(1, Token::Type::FALSE))
|
||||||
|
return new Literal(false);
|
||||||
|
if (match(1, Token::Type::TRUE))
|
||||||
|
return new Literal(true);
|
||||||
|
if (match(1, Token::Type::NIL))
|
||||||
|
return new Literal(new Void());
|
||||||
|
if (match(1, Token::Type::NUMBER)) {
|
||||||
|
return new Literal(stod(previous()->literal));
|
||||||
|
}
|
||||||
|
if (match(1, Token::Type::STRING)) {
|
||||||
|
return new Literal(previous()->literal);
|
||||||
|
}
|
||||||
|
if (match(1, Token::Type::LEFT_PAREN)) {
|
||||||
|
Expression *e = expression();
|
||||||
|
consume(Token::Type::RIGHT_PAREN, "Expect ')'.");
|
||||||
|
return new Grouping(e);
|
||||||
|
}
|
||||||
|
throw runtime_error("Expected an expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *Parser::unary() {
|
||||||
|
if (match(2, Token::BANG, Token::Type::MINUS)) {
|
||||||
|
Token *op = previous();
|
||||||
|
Expression *right = unary();
|
||||||
|
return new Unary(op, right);
|
||||||
|
}
|
||||||
|
return primary();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *Parser::expression() { return equality(); }
|
||||||
|
|
||||||
|
Expression *Parser::factor() {
|
||||||
|
Expression *expr = unary();
|
||||||
|
while (match(2, Token::Type::SLASH, Token::Type::STAR)) {
|
||||||
|
Token *op = previous();
|
||||||
|
Expression *right = unary();
|
||||||
|
expr = new Binary(expr, op, right);
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *Parser::term() {
|
||||||
|
Expression *expr = factor();
|
||||||
|
while (match(2, Token::Type::MINUS, Token::Type::PLUS)) {
|
||||||
|
Token *op = previous();
|
||||||
|
Expression *right = unary();
|
||||||
|
expr = new Binary(expr, op, right);
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *Parser::equality(void) {
|
||||||
|
Expression *expr = comparison();
|
||||||
|
|
||||||
|
while (match(2, Token::Type::BANG_EQUAL, Token::Type::BANG_EQUAL)) {
|
||||||
|
Token *op = previous();
|
||||||
|
Expression *right = comparison();
|
||||||
|
return new Binary(expr, op, right);
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *Parser::comparison(void) {
|
||||||
|
Expression *expr = term();
|
||||||
|
while (match(4, Token::Type::GREATER, Token::Type::GREATER_EQUAL,
|
||||||
|
Token::Type::LESS, Token::Type::LESS_EQUAL)) {
|
||||||
|
Token *op = previous();
|
||||||
|
Expression *right = term();
|
||||||
|
expr = new Binary(expr, op, right);
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
|
||||||
133
src/parser.hpp
133
src/parser.hpp
|
|
@ -89,125 +89,22 @@ class Parser {
|
||||||
vector<Token> tokens;
|
vector<Token> tokens;
|
||||||
int current_token;
|
int current_token;
|
||||||
|
|
||||||
Token peek() { return tokens[current_token]; };
|
Token peek();
|
||||||
|
bool is_at_end();
|
||||||
bool is_at_end() { return peek().tokentype == Token::END_OF_FILE; };
|
Token *previous();
|
||||||
|
Token *advance();
|
||||||
Token *previous() { return &tokens[current_token - 1]; };
|
bool check(Token::Type type);
|
||||||
|
bool match(int count, ...);
|
||||||
Token *advance() {
|
Token *consume(Token::Type typ, string message);
|
||||||
if (!is_at_end())
|
runtime_error error(Token token, string message);
|
||||||
current_token += 1;
|
Expression *primary();
|
||||||
return previous();
|
Expression *unary();
|
||||||
}
|
Expression *expression();
|
||||||
|
Expression *factor();
|
||||||
bool check(Token::Type type) {
|
Expression *term();
|
||||||
if (is_at_end()) {
|
Expression *equality(void);
|
||||||
return false;
|
Expression *comparison(void);
|
||||||
}
|
|
||||||
return peek().tokentype == type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool match(int count, ...) {
|
|
||||||
va_list list;
|
|
||||||
va_start(list, count);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
Token::Type ttc = va_arg(list, Token::Type);
|
|
||||||
// cout << token_name(ttc) << "\n";
|
|
||||||
if (check(ttc)) {
|
|
||||||
advance();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
Token *consume(Token::Type typ, string message) {
|
|
||||||
if (check(typ)) {
|
|
||||||
return advance();
|
|
||||||
}
|
|
||||||
throw error(peek(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
runtime_error error(Token token, string message) {
|
|
||||||
cout << token.as_string() << " " << message;
|
|
||||||
return runtime_error(message); // TODO no exceptions
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression *primary() {
|
|
||||||
if (match(1, Token::Type::FALSE))
|
|
||||||
return new Literal(false);
|
|
||||||
if (match(1, Token::Type::TRUE))
|
|
||||||
return new Literal(true);
|
|
||||||
if (match(1, Token::Type::NIL))
|
|
||||||
return new Literal(new Void());
|
|
||||||
if (match(1, Token::Type::NUMBER)) {
|
|
||||||
return new Literal(stod(previous()->literal));
|
|
||||||
}
|
|
||||||
if (match(1, Token::Type::STRING)) {
|
|
||||||
return new Literal(previous()->literal);
|
|
||||||
}
|
|
||||||
if (match(1, Token::Type::LEFT_PAREN)) {
|
|
||||||
Expression *e = expression();
|
|
||||||
consume(Token::Type::RIGHT_PAREN, "Expect ')'.");
|
|
||||||
return new Grouping(e);
|
|
||||||
}
|
|
||||||
throw runtime_error("Expected an expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Expression *parse(vector<Token> tokenlist);
|
Expression *parse(vector<Token> tokenlist);
|
||||||
Expression *unary() {
|
|
||||||
if (match(2, Token::BANG, Token::Type::MINUS)) {
|
|
||||||
Token *op = previous();
|
|
||||||
Expression *right = unary();
|
|
||||||
return new Unary(op, right);
|
|
||||||
}
|
|
||||||
return primary();
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression *expression() { return equality(); }
|
|
||||||
|
|
||||||
Expression *factor() {
|
|
||||||
Expression *expr = unary();
|
|
||||||
while (match(2, Token::Type::SLASH, Token::Type::STAR)) {
|
|
||||||
Token *op = previous();
|
|
||||||
Expression *right = unary();
|
|
||||||
expr = new Binary(expr, op, right);
|
|
||||||
}
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression *term() {
|
|
||||||
Expression *expr = factor();
|
|
||||||
while (match(2, Token::Type::MINUS, Token::Type::PLUS)) {
|
|
||||||
Token *op = previous();
|
|
||||||
Expression *right = unary();
|
|
||||||
expr = new Binary(expr, op, right);
|
|
||||||
}
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression *equality(void) {
|
|
||||||
Expression *expr = comparison();
|
|
||||||
|
|
||||||
while (match(2, Token::Type::BANG_EQUAL, Token::Type::BANG_EQUAL)) {
|
|
||||||
Token *op = previous();
|
|
||||||
Expression *right = comparison();
|
|
||||||
return new Binary(expr, op, right);
|
|
||||||
}
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression *comparison(void) {
|
|
||||||
Expression *expr = term();
|
|
||||||
while (match(4, Token::Type::GREATER, Token::Type::GREATER_EQUAL,
|
|
||||||
Token::Type::LESS, Token::Type::LESS_EQUAL)) {
|
|
||||||
Token *op = previous();
|
|
||||||
Expression *right = term();
|
|
||||||
expr = new Binary(expr, op, right);
|
|
||||||
}
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue