Skip to content

Commit

Permalink
Implemented if-else conditional statemetns.
Browse files Browse the repository at this point in the history
  • Loading branch information
iamsayantan committed Apr 14, 2022
1 parent 40e9cde commit 37c4f98
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 3 deletions.
21 changes: 21 additions & 0 deletions interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,27 @@ func (i *Interpreter) VisitExpressionExpr(expr *Expression) error {
return nil
}

func (i *Interpreter) VisitIfStmt(stmt *IfStmt) error {
condition, err := i.evaluate(stmt.Condition)
if err != nil {
return err
}

if i.isTruthy(condition) {
err := i.execute(stmt.ThenBranch)
if err != nil {
return err
}
} else if stmt.ElseBranch != nil {
err := i.execute(stmt.ElseBranch)
if err != nil {
return err
}
}

return nil
}

func (i *Interpreter) VisitPrintExpr(expr *Print) error {
val, err := i.evaluate(expr.Expression)
if err != nil {
Expand Down
41 changes: 41 additions & 0 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ func (p *Parser) varDeclaration() (Stmt, error) {
// statement --> exprStmt
// | printStmt
func (p *Parser) statement() (Stmt, error) {
if p.match(If) {
return p.ifStatement()
}

if p.match(PRINT) {
return p.printStatement()
}
Expand All @@ -110,6 +114,43 @@ func (p *Parser) statement() (Stmt, error) {
return p.expressionStatement()
}

func (p *Parser) ifStatement() (Stmt, error) {
// The parenthesis around the if statement is only half useful. We need some kind of delimiter between
// the condition and the then statement, otherwise the parser can't tell when it has reached the end
// of the condition. But the opening parenthesis in the if condition doesn't do anything useful, it's
// only there because otherwise we'd end up with unbalanced parenthesis. Go requires the statement to
// be braced block, so the '{' acts as the end of the condition.
_, err := p.consume(LeftParen, "Expected '(' after 'if'")
if err != nil {
return nil, err
}

condition, err := p.expression()
if err != nil {
return nil, err
}

_, err = p.consume(RightParen, "Expect ')' after if condition.")
if err != nil {
return nil, err
}

thenBranch, err := p.statement()
if err != nil {
return nil, err
}

var elseBranch Stmt = nil
if p.match(Else) {
elseBranch, err = p.statement()
if err != nil {
return nil, err
}
}

return &IfStmt{Condition: condition, ThenBranch: thenBranch, ElseBranch: elseBranch}, nil
}

// block parses a block of statements when it encounters a '{'.
func (p *Parser) block() ([]Stmt, error) {
statements := make([]Stmt, 0)
Expand Down
17 changes: 14 additions & 3 deletions stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,35 @@ type Stmt interface {
}

type StmtVisitor interface {
VisitBlockStmt(stmt *Block) error
VisitBlockStmt(stmt *Block) error
VisitExpressionExpr(expr *Expression) error
VisitPrintExpr(expr *Print) error
VisitVarStmt(expr *VarStmt) error
VisitIfStmt(stmt *IfStmt) error
}

type Block struct {
Statements []Stmt
Statements []Stmt
}

func (b *Block) Accept(visitor StmtVisitor) error {
return visitor.VisitBlockStmt(b)
return visitor.VisitBlockStmt(b)
}

type Expression struct {
Expression Expr
}

type IfStmt struct {
Condition Expr
ThenBranch Stmt
ElseBranch Stmt
}

func (i *IfStmt) Accept(visitor StmtVisitor) error {
return visitor.VisitIfStmt(i)
}

func (e *Expression) Accept(visitor StmtVisitor) error {
return visitor.VisitExpressionExpr(e)
}
Expand Down

0 comments on commit 37c4f98

Please sign in to comment.