diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb
index 1e14e53..7ac47d3 100644
--- a/ruby/lib/lox/parser.rb
+++ b/ruby/lib/lox/parser.rb
@@ -23,6 +23,7 @@ module Lox
private
def declaration
+ return function("function") if match?(:FUN)
return var_declaration if match?(:VAR)
statement
@@ -116,6 +117,26 @@ module Lox
Stmt::Expr.new(value)
end
+ def function(kind)
+ name = consume!(:IDENTIFIER, "Expect #{kind} name.")
+ consume!(:LEFT_PAREN, "Expect '(' after #{kind} name.")
+ params = []
+ unless check?(:RIGHT_PAREN)
+ loop do
+ raise ParseError.new(peek, "Can't have more than 255 parameters.") if params.size >= 255
+
+ params << consume!(:IDENTIFIER, "Expect parameter name.")
+ break unless match?(:COMMA)
+ end
+ end
+ consume!(:RIGHT_PAREN, "Expect ')' after parameters.")
+
+ consume!(:LEFT_BRACE, "Expect '{' before #{kind} body.")
+ body = block
+
+ Stmt::Function.new(name, params, body)
+ end
+
def block
statements = []
until check?(:RIGHT_BRACE) || eot?
diff --git a/ruby/lib/lox/stmt.rb b/ruby/lib/lox/stmt.rb
index c526e04..0f377d7 100644
--- a/ruby/lib/lox/stmt.rb
+++ b/ruby/lib/lox/stmt.rb
@@ -13,6 +13,7 @@ module Lox
end
stmt :Block, :stmts
+ stmt :Fun, :name, :params, :body
stmt :Expr, :expr
stmt :If, :cond, :then, :else
stmt :Print, :expr