Browse Source

Use method and classmethod keywords

master
Dylan Baker 1 year ago
parent
commit
0d9a817b2b

+ 6
- 4
lib/ahem/ast/class_definition.rb View File

@@ -1,16 +1,18 @@
1 1
 class AST::ClassDefinition
2
-  attr_reader :name, :members, :methods
2
+  attr_reader :name, :members, :instance_methods, :class_methods
3 3
 
4
-  def initialize(name, members, methods)
4
+  def initialize(name, members, instance_methods, class_methods)
5 5
     @name = name
6 6
     @members = members
7
-    @methods = methods
7
+    @instance_methods = instance_methods
8
+    @class_methods = class_methods
8 9
   end
9 10
 
10 11
   def ==(other)
11 12
     other.is_a?(AST::ClassDefinition) && other.name == @name &&
12 13
       other.members == @members &&
13
-      other.methods == @methods
14
+      other.instance_methods == @instance_methods
15
+      other.class_methods == @class_methods
14 16
   end
15 17
 
16 18
   def execute(env)

+ 6
- 0
lib/ahem/lexer.rb View File

@@ -149,6 +149,12 @@ class Lexer
149 149
     elsif source.match(/\Afunction/)
150 150
       @position += 8
151 151
       Token.new(TokenKinds::FUNCTION)
152
+    elsif source.match(/\Amethod/)
153
+      @position += 6
154
+      Token.new(TokenKinds::METHOD)
155
+    elsif source.match(/\Aclassmethod/)
156
+      @position += 11
157
+      Token.new(TokenKinds::CLASSMETHOD)
152 158
     elsif source.match(/\Aclass/)
153 159
       @position += 5
154 160
       Token.new(TokenKinds::CLASS)

+ 24
- 4
lib/ahem/parser.rb View File

@@ -50,6 +50,20 @@ class Parser
50 50
 
51 51
   def function_definition
52 52
     eat(TokenKinds::FUNCTION)
53
+    _function_definition
54
+  end
55
+
56
+  def method_definition
57
+    eat(TokenKinds::METHOD)
58
+    _function_definition
59
+  end
60
+
61
+  def classmethod_definition
62
+    eat(TokenKinds::CLASSMETHOD)
63
+    _function_definition
64
+  end
65
+
66
+  def _function_definition
53 67
     name = identifier
54 68
     params = parameters
55 69
     body = block
@@ -90,14 +104,20 @@ class Parser
90 104
       eat(TokenKinds::SEMICOLON)
91 105
     end
92 106
 
93
-    methods = Array.new
94
-    while @current_token.type == TokenKinds::FUNCTION
95
-      methods << function_definition
107
+    class_methods = Array.new
108
+    instance_methods = Array.new
109
+    while [TokenKinds::METHOD, TokenKinds::CLASSMETHOD].include?(@current_token.type)
110
+      case @current_token.type
111
+      when TokenKinds::METHOD
112
+        instance_methods << method_definition
113
+      when TokenKinds::CLASSMETHOD
114
+        class_methods << classmethod_definition
115
+      end
96 116
     end
97 117
 
98 118
     eat(TokenKinds::RBRACE)
99 119
 
100
-    AST::ClassDefinition.new(class_name, property_declarations, methods)
120
+    AST::ClassDefinition.new(class_name, property_declarations, instance_methods, class_methods)
101 121
   end
102 122
 
103 123
   def conditional

+ 2
- 0
lib/ahem/token_kinds.rb View File

@@ -2,6 +2,7 @@ module TokenKinds
2 2
   ATOM = :atom
3 3
   BOOLEAN = :boolean
4 4
   CLASS = :class
5
+  CLASSMETHOD = :classmethod
5 6
   CLASS_NAME = :class_name
6 7
   COMMA = :comma
7 8
   DOT = :dot
@@ -19,6 +20,7 @@ module TokenKinds
19 20
   LBRACKET = :lbracket
20 21
   LPAREN = :lparen
21 22
   LET = :let
23
+  METHOD = :method
22 24
   NULL = :null
23 25
   NUMBER = :number
24 26
   OPERATOR = :operator

+ 1
- 1
spec/ast/class_definition_spec.rb View File

@@ -1,7 +1,7 @@
1 1
 RSpec.describe AST::ClassDefinition do
2 2
   it 'defines a class' do
3 3
     env = Environment.new(env)
4
-    klass = AST::ClassDefinition.new(AST::Identifier.new('Class'), [], [])
4
+    klass = AST::ClassDefinition.new(AST::Identifier.new('Class'), [], [], [])
5 5
     klass.execute(env)
6 6
     expect(env.get('Class')).to eq(klass)
7 7
   end

+ 10
- 0
spec/lexer_spec.rb View File

@@ -184,4 +184,14 @@ RSpec.describe Lexer do
184 184
       [Token.new(TokenKinds::HASH), Token.new(TokenKinds::EOF)]
185 185
     )
186 186
   end
187
+
188
+  it 'lexes method and classmethod' do
189
+    expect(Lexer.new('method classmethod').scan_all).to eq(
190
+      [
191
+        Token.new(TokenKinds::METHOD),
192
+        Token.new(TokenKinds::CLASSMETHOD),
193
+        Token.new(TokenKinds::EOF)
194
+      ]
195
+    )
196
+  end
187 197
 end

+ 13
- 3
spec/parser_spec.rb View File

@@ -281,8 +281,11 @@ RSpec.describe Parser do
281 281
           class Class {
282 282
             public foo, bar;
283 283
             private baz;
284
-            function method() {
285
-              "method";
284
+            method my_method() {
285
+              "my method";
286
+            }
287
+            classmethod my_classmethod() {
288
+              "my classmethod";
286 289
             }
287 290
           }
288 291
         CLASS
@@ -297,10 +300,17 @@ RSpec.describe Parser do
297 300
           ],
298 301
           [
299 302
             AST::FunctionDefinition.new(
300
-              AST::Identifier.new('method'),
303
+              AST::Identifier.new('my_method'),
301 304
               [],
302 305
               AST::Block.new([AST::String.new('method')])
303 306
             )
307
+          ],
308
+          [
309
+            AST::FunctionDefinition.new(
310
+              AST::Identifier.new('my_classmethod'),
311
+              [],
312
+              AST::Block.new([AST::String.new('my classmethod')])
313
+            )
304 314
           ]
305 315
         )
306 316
       ]

Loading…
Cancel
Save