Przeglądaj źródła

Parse numbers

master
Dylan Baker 6 lat temu
rodzic
commit
3d230605bf
5 zmienionych plików z 71 dodań i 0 usunięć
  1. 2
    0
      lib/chervil.rb
  2. 3
    0
      lib/chervil/ast.rb
  3. 13
    0
      lib/chervil/ast/number.rb
  4. 40
    0
      lib/chervil/parser.rb
  5. 13
    0
      spec/parser_spec.rb

+ 2
- 0
lib/chervil.rb Wyświetl plik

@@ -1,3 +1,5 @@
1
+require 'chervil/ast'
1 2
 require 'chervil/lexer'
3
+require 'chervil/parser'
2 4
 require 'chervil/token'
3 5
 require 'chervil/version'

+ 3
- 0
lib/chervil/ast.rb Wyświetl plik

@@ -0,0 +1,3 @@
1
+module Chervil::AST
2
+  require "chervil/ast/number"
3
+end

+ 13
- 0
lib/chervil/ast/number.rb Wyświetl plik

@@ -0,0 +1,13 @@
1
+module Chervil::AST
2
+  class Number
3
+    attr_reader :value
4
+
5
+    def initialize(value)
6
+      @value = value
7
+    end
8
+
9
+    def ==(other)
10
+      @value == other.value
11
+    end
12
+  end
13
+end

+ 40
- 0
lib/chervil/parser.rb Wyświetl plik

@@ -0,0 +1,40 @@
1
+module Chervil
2
+  class Parser
3
+    def initialize(lexer)
4
+      @lexer = lexer
5
+      @tree = Array.new
6
+      @current_token = @lexer.get_next_token
7
+    end
8
+
9
+    def parse
10
+      until @current_token.type == :eof
11
+        @tree << expr
12
+      end
13
+      @tree
14
+    end
15
+
16
+    def expr
17
+      if @current_token.type == :number
18
+        constant
19
+      end
20
+    end
21
+
22
+    def constant
23
+      case @current_token.type
24
+      when :number
25
+        token = eat(:number)
26
+        AST::Number.new(token.value.to_f)
27
+      end
28
+    end
29
+
30
+    def eat(type)
31
+      if @current_token.type == type
32
+        token = @current_token
33
+        @current_token = @lexer.get_next_token
34
+        token
35
+      else
36
+        raise "Expected #{type} but got #{@current_token.type}"
37
+      end
38
+    end
39
+  end
40
+end

+ 13
- 0
spec/parser_spec.rb Wyświetl plik

@@ -0,0 +1,13 @@
1
+module Chervil
2
+  RSpec.describe Parser do
3
+    def parse(source)
4
+      lexer = Lexer.new(source)
5
+      parser = Parser.new(lexer)
6
+      parser.parse
7
+    end
8
+
9
+    it 'parses a number' do
10
+      expect(parse("1").first).to eq(AST::Number.new(1.0))
11
+    end
12
+  end
13
+end

Ładowanie…
Anuluj
Zapisz