Skip to content

Commit

Permalink
support prefix and postfix ++,-- and bugfix
Browse files Browse the repository at this point in the history
++,-- returns rvalue. no ----a bullshit.
  • Loading branch information
rapiz1 committed Oct 30, 2021
1 parent 72c4f9c commit 7ed82b2
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 16 deletions.
40 changes: 38 additions & 2 deletions ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,48 @@ void EvalVisitor::visit(Unary* expr) {
EvalVisitor v(context);
v.visit(expr->child);
Expr* e = v.value;
Number* n = dynamic_cast<Number*>(e);
Boolean* b = dynamic_cast<Boolean*>(e);
Variable* var = dynamic_cast<Variable*>(expr->child);
switch (expr->op.tokenType) {
case MINUS:
value = new Number(-dynamic_cast<Number*>(e)->value);
value = new Number(-n->value);
break;
case BANG:
value = new Boolean(dynamic_cast<Literal*>(e)->isTruthy());
value = new Boolean(!b->isTruthy());
break;
case PLUSPLUS:
assert(var);
value = new Number(n->value + 1);
context.set(var->name, value);
break;
case MINUSMINUS:
assert(var);
value = new Number(n->value - 1);
context.set(var->name, value);
break;
default:
throw RuntimeError();
break;
}
}

void EvalVisitor::visit(Postfix* expr) {
EvalVisitor v(context);
v.visit(expr->child);
Expr* e = v.value;
Number* n = dynamic_cast<Number*>(e);
Variable* var = dynamic_cast<Variable*>(expr->child);
assert(n);
assert(var);
switch (expr->op.tokenType) {
case PLUSPLUS:
value = new Number(n->value);
context.set(var->name, new Number(n->value + 1));
break;
case MINUSMINUS:
value = new Number(n->value);
context.set(var->name, new Number(n->value - 1));
break;
default:
throw RuntimeError();
Expand Down
17 changes: 17 additions & 0 deletions ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Expr;
class Literal;
class Binary;
class Unary;
class Postfix;
class Variable;
class Call;

Expand Down Expand Up @@ -69,6 +70,7 @@ class ExprVisitor {
virtual void visit(Literal* expr) = 0;
virtual void visit(Binary* expr) = 0;
virtual void visit(Unary* expr) = 0;
virtual void visit(Postfix* expr) = 0;
virtual void visit(Variable* expr) = 0;
virtual void visit(Call* expr) = 0;
};
Expand All @@ -92,6 +94,7 @@ class EvalVisitor : public ExprVisitor {
void visit(Literal* expr);
void visit(Binary* expr);
void visit(Unary* expr);
void visit(Postfix* expr);
void visit(Variable* expr);
void visit(Call* expr);
Literal* getValue() { return value; }
Expand Down Expand Up @@ -282,6 +285,20 @@ class Unary : public Expr {
friend class EvalVisitor;
};

class Postfix : public Expr {
protected:
Token op;
Expr* child;

public:
Postfix(Token op, Expr* child) : op(op), child(child){};
operator std::string() { return "postfix " + op.lexeme; };
bool isLval() const override { return false; }

void accept(ExprVisitor* v) { v->visit(this); }
friend class EvalVisitor;
};

class Literal : public Expr {
public:
virtual bool isTruthy() = 0;
Expand Down
24 changes: 20 additions & 4 deletions parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cassert>
#include <cstdarg>
#include <iostream>
#include <stack>

void Parser::checkEof() {
if (eof()) {
Expand Down Expand Up @@ -347,12 +348,27 @@ Expr* Parser::factor() {
}

Expr* Parser::unary() {
if (match(2, MINUS, BANG)) {
std::stack<Token> st;
while (match(4, MINUS, BANG, PLUSPLUS, MINUSMINUS)) {
Token op = advance();
return new Unary(op, primary());
} else {
return call();
st.push(op);
}
Expr* e = postfix();
while (!st.empty()) {
auto op = st.top();
st.pop();
e = new Unary(op, e);
}
return e;
}

Expr* Parser::postfix() {
Expr* p = call();
while (match(2, PLUSPLUS, MINUSMINUS)) {
Token op = advance();
p = new Postfix(op, p);
}
return p;
}

Expr* Parser::call() {
Expand Down
17 changes: 9 additions & 8 deletions parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ class Parser {
Args args(); // ID (, ID)*
RealArgs real_args(); // EXPR (, EXPR)*

Expr* expression();
Expr* assignment();
Expr* equality();
Expr* comparsion();
Expr* term();
Expr* factor();
Expr* unary(); // UNARY = CALL | (! | -) CALL
Expr* call(); // CALL = PRIM ('(' ARGS? ')')*
Expr* expression(); // ASSIGN
Expr* assignment(); // LVAL '=' EQUALITY | EQUALITY
Expr* equality(); // COMP ('==' | '!=') COMP | COMP
Expr* comparsion(); // TERM ('>' | '>=' | '<' | '<=') TERM | TERM
Expr* term(); // FACTOR (('+' | '-') FACTOR)*
Expr* factor(); // UNARY (('/' | '*') UNARY)*
Expr* unary(); // (! | - | -- | ++)* POSTFIX
Expr* postfix(); // CALL (++ | --)*
Expr* call(); // PRIM ('(' ARGS? ')')*
Expr* primary();

public:
Expand Down
4 changes: 2 additions & 2 deletions scanner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ void Scanner::scanToken() {
addToken(STAR);
break;
case '+':
addToken(PLUS);
addToken(match('+') ? PLUSPLUS : PLUS);
break;
case '-':
addToken(MINUS);
addToken(match('-') ? MINUSMINUS : MINUS);
break;
case '/':
if (match('/')) {
Expand Down
2 changes: 2 additions & 0 deletions token.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ enum TokenType {
GREATER_EQUAL,
LESS,
LESS_EQUAL,
PLUSPLUS,
MINUSMINUS,

// Literals.
IDENTIFIER,
Expand Down

0 comments on commit 7ed82b2

Please sign in to comment.