Alpha Chen 2 years ago
parent 1b0a2b3a7a
commit f83031935f

@ -49,6 +49,14 @@ module Lox
parenthesize("while", stmt.cond, stmt.body)
end
def visit_class(stmt)
parenthesize("class #{stmt.name.lexeme}", *stmt.methods)
end
def visit_function(stmt)
parenthesize("function #{stmt.name.lexeme}", *stmt.body)
end
private
def parenthesize(name, *exprs)

@ -0,0 +1,19 @@
require_relative "instance"
module Lox
class LoxClass
attr_reader :name
def initialize(name)
@name = name
end
def to_s = name
def call(interpreter, args) = Instance.new(self)
def arity = 0
end
end

@ -23,12 +23,27 @@ module Lox
private
def declaration
return class_decl if match?(:CLASS)
return function("function") if match?(:FUN)
return var_declaration if match?(:VAR)
statement
end
def class_decl
name = consume!(:IDENTIFIER, "Expect class name.")
consume!(:LEFT_BRACE, "Expect '{' before class body.")
methods = []
until check?(:RIGHT_BRACE) || eot?
methods << function("method")
end
consume!(:RIGHT_BRACE, "Expect '}' after class body.")
Stmt::Class.new(name, methods)
end
def var_declaration
name = consume!(:IDENTIFIER, "Expect variable name.")
initializer = match?(:EQUAL) ? expression : nil

@ -13,8 +13,9 @@ module Lox
end
stmt :Block, :stmts
stmt :Function, :name, :params, :body
stmt :Class, :name, :methods
stmt :Expr, :expr
stmt :Function, :name, :params, :body
stmt :If, :cond, :then, :else
stmt :Print, :expr
stmt :Return, :keyword, :value

@ -96,6 +96,22 @@ class TestParser < Lox::Test
AST
end
def test_class
assert_parsed <<~AST.chomp, :declaration, <<~SRC
(class Breakfast (function cook (print Eggs a-fryin'!)) (function serve (print (+ (+ Enjoy your breakfast, (var who)) .))))
AST
class Breakfast {
cook() {
print "Eggs a-fryin'!";
}
serve(who) {
print "Enjoy your breakfast, " + who + ".";
}
}
SRC
end
private
def assert_parsed(expected, name, src)

Loading…
Cancel
Save