Browse Source

Implement quoted values

master
Dylan Baker 6 years ago
parent
commit
1e1f64a141
6 changed files with 53 additions and 4 deletions
  1. 1
    0
      lib/chervil/ast.rb
  2. 21
    0
      lib/chervil/ast/quotation.rb
  3. 4
    1
      lib/chervil/lexer.rb
  4. 8
    0
      lib/chervil/parser.rb
  5. 5
    3
      spec/lexer_spec.rb
  6. 14
    0
      spec/parser_spec.rb

+ 1
- 0
lib/chervil/ast.rb View File

9
     require "chervil/ast/identifier"
9
     require "chervil/ast/identifier"
10
     require "chervil/ast/list"
10
     require "chervil/ast/list"
11
     require "chervil/ast/number"
11
     require "chervil/ast/number"
12
+    require "chervil/ast/quotation"
12
     require "chervil/ast/string"
13
     require "chervil/ast/string"
13
   end
14
   end
14
 end
15
 end

+ 21
- 0
lib/chervil/ast/quotation.rb View File

1
+module Chervil::AST
2
+  class Quotation
3
+    attr_reader :value
4
+
5
+    def initialize(value)
6
+      @value = value
7
+    end
8
+
9
+    def evaluate(env)
10
+      if @value.is_a?(List)
11
+        @value.elements
12
+      else
13
+        @value.evaluate(env)
14
+      end
15
+    end
16
+
17
+    def ==(other)
18
+      @value == other.value
19
+    end
20
+  end
21
+end

+ 4
- 1
lib/chervil/lexer.rb View File

38
         else
38
         else
39
           raise "Unexpected character #{current_char}"
39
           raise "Unexpected character #{current_char}"
40
         end
40
         end
41
-      when '"', '\''
41
+      when '\''
42
+        advance
43
+        Token.new(:quote, '\'')
44
+      when '"'
42
         delimiter = current_char
45
         delimiter = current_char
43
         advance
46
         advance
44
         string = String.new
47
         string = String.new

+ 8
- 0
lib/chervil/parser.rb View File

22
         identifier
22
         identifier
23
       elsif @current_token.type == :lparen
23
       elsif @current_token.type == :lparen
24
         list
24
         list
25
+      elsif @current_token.type == :quote
26
+        quotation
25
       else
27
       else
26
         @error = Error.new("Unexpected token #{@current_token.type}: #{@current_token.value}")
28
         @error = Error.new("Unexpected token #{@current_token.type}: #{@current_token.value}")
27
       end
29
       end
28
     end
30
     end
29
 
31
 
32
+    def quotation
33
+      eat(:quote)
34
+      value = expr
35
+      AST::Quotation.new(value)
36
+    end
37
+
30
     def list
38
     def list
31
       eat(:lparen)
39
       eat(:lparen)
32
 
40
 

+ 5
- 3
spec/lexer_spec.rb View File

39
       expect(Lexer.new('"hello"').get_next_token).to eq(
39
       expect(Lexer.new('"hello"').get_next_token).to eq(
40
         Token.new(:string, 'hello')
40
         Token.new(:string, 'hello')
41
       )
41
       )
42
-      expect(Lexer.new("'world'").get_next_token).to eq(
43
-        Token.new(:string, 'world')
44
-      )
45
     end
42
     end
46
 
43
 
47
     it 'lexes booleans' do
44
     it 'lexes booleans' do
54
       lexer = Lexer.new('"hello world')
51
       lexer = Lexer.new('"hello world')
55
       expect(lexer.get_next_token).to eq(Error.new("Unterminated string"))
52
       expect(lexer.get_next_token).to eq(Error.new("Unterminated string"))
56
     end
53
     end
54
+
55
+    it 'lexes quotes' do
56
+      lexer = Lexer.new('\'')
57
+      expect(lexer.get_next_token).to eq(Token.new(:quote, '\''))
58
+    end
57
   end
59
   end
58
 end
60
 end

+ 14
- 0
spec/parser_spec.rb View File

97
         )
97
         )
98
       )
98
       )
99
     end
99
     end
100
+
101
+    it 'parses a quoted value' do
102
+      expect(parse('\'(1 2 3)').first).to eq(
103
+        AST::Quotation.new(
104
+          AST::List.new(
105
+            [
106
+              AST::Number.new(1.0),
107
+              AST::Number.new(2.0),
108
+              AST::Number.new(3.0),
109
+            ]
110
+          )
111
+        )
112
+      )
113
+    end
100
   end
114
   end
101
 end
115
 end

Loading…
Cancel
Save