Browse Source

Use method and classmethod keywords

master
Dylan Baker 4 years ago
parent
commit
0d9a817b2b

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

1
 class AST::ClassDefinition
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
     @name = name
5
     @name = name
6
     @members = members
6
     @members = members
7
-    @methods = methods
7
+    @instance_methods = instance_methods
8
+    @class_methods = class_methods
8
   end
9
   end
9
 
10
 
10
   def ==(other)
11
   def ==(other)
11
     other.is_a?(AST::ClassDefinition) && other.name == @name &&
12
     other.is_a?(AST::ClassDefinition) && other.name == @name &&
12
       other.members == @members &&
13
       other.members == @members &&
13
-      other.methods == @methods
14
+      other.instance_methods == @instance_methods
15
+      other.class_methods == @class_methods
14
   end
16
   end
15
 
17
 
16
   def execute(env)
18
   def execute(env)

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

149
     elsif source.match(/\Afunction/)
149
     elsif source.match(/\Afunction/)
150
       @position += 8
150
       @position += 8
151
       Token.new(TokenKinds::FUNCTION)
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
     elsif source.match(/\Aclass/)
158
     elsif source.match(/\Aclass/)
153
       @position += 5
159
       @position += 5
154
       Token.new(TokenKinds::CLASS)
160
       Token.new(TokenKinds::CLASS)

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

50
 
50
 
51
   def function_definition
51
   def function_definition
52
     eat(TokenKinds::FUNCTION)
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
     name = identifier
67
     name = identifier
54
     params = parameters
68
     params = parameters
55
     body = block
69
     body = block
90
       eat(TokenKinds::SEMICOLON)
104
       eat(TokenKinds::SEMICOLON)
91
     end
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
     end
116
     end
97
 
117
 
98
     eat(TokenKinds::RBRACE)
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
   end
121
   end
102
 
122
 
103
   def conditional
123
   def conditional

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

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

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

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

+ 10
- 0
spec/lexer_spec.rb View File

184
       [Token.new(TokenKinds::HASH), Token.new(TokenKinds::EOF)]
184
       [Token.new(TokenKinds::HASH), Token.new(TokenKinds::EOF)]
185
     )
185
     )
186
   end
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
 end
197
 end

+ 13
- 3
spec/parser_spec.rb View File

281
           class Class {
281
           class Class {
282
             public foo, bar;
282
             public foo, bar;
283
             private baz;
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
         CLASS
291
         CLASS
297
           ],
300
           ],
298
           [
301
           [
299
             AST::FunctionDefinition.new(
302
             AST::FunctionDefinition.new(
300
-              AST::Identifier.new('method'),
303
+              AST::Identifier.new('my_method'),
301
               [],
304
               [],
302
               AST::Block.new([AST::String.new('method')])
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