diff --git a/ruby/lib/lox/ast_printer.rb b/ruby/lib/lox/ast_printer.rb
index 6fb8f45..8a89523 100644
--- a/ruby/lib/lox/ast_printer.rb
+++ b/ruby/lib/lox/ast_printer.rb
@@ -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)
diff --git a/ruby/lib/lox/lox_class.rb b/ruby/lib/lox/lox_class.rb
new file mode 100644
index 0000000..170fa36
--- /dev/null
+++ b/ruby/lib/lox/lox_class.rb
@@ -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
diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb
index 2c1ecf8..f087ec4 100644
--- a/ruby/lib/lox/parser.rb
+++ b/ruby/lib/lox/parser.rb
@@ -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
diff --git a/ruby/lib/lox/stmt.rb b/ruby/lib/lox/stmt.rb
index e4bfc54..23d31a6 100644
--- a/ruby/lib/lox/stmt.rb
+++ b/ruby/lib/lox/stmt.rb
@@ -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
diff --git a/ruby/test/lox/test_parser.rb b/ruby/test/lox/test_parser.rb
index 0e73a26..8b02820 100644
--- a/ruby/test/lox/test_parser.rb
+++ b/ruby/test/lox/test_parser.rb
@@ -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)