Parcourir la source

Parse conditionals

master
Dylan Baker il y a 5 ans
Parent
révision
b3735912f5
4 fichiers modifiés avec 43 ajouts et 2 suppressions
  1. 1
    0
      lib/chervil/ast.rb
  2. 17
    0
      lib/chervil/ast/conditional.rb
  3. 15
    2
      lib/chervil/parser.rb
  4. 10
    0
      spec/parser_spec.rb

+ 1
- 0
lib/chervil/ast.rb Voir le fichier

4
   module AST
4
   module AST
5
     require "chervil/ast/application"
5
     require "chervil/ast/application"
6
     require "chervil/ast/boolean"
6
     require "chervil/ast/boolean"
7
+    require "chervil/ast/conditional"
7
     require "chervil/ast/definition"
8
     require "chervil/ast/definition"
8
     require "chervil/ast/function"
9
     require "chervil/ast/function"
9
     require "chervil/ast/identifier"
10
     require "chervil/ast/identifier"

+ 17
- 0
lib/chervil/ast/conditional.rb Voir le fichier

1
+module Chervil::AST
2
+  class Conditional
3
+    attr_reader :predicate
4
+    attr_reader :true_branch
5
+    attr_reader :false_branch
6
+
7
+    def initialize(predicate, true_branch, false_branch)
8
+      @predicate = predicate
9
+      @true_branch = true_branch
10
+      @false_branch = false_branch
11
+    end
12
+
13
+    def ==(other)
14
+      @predicate == other.predicate && @true_branch == other.true_branch && @false_branch == other.false_branch
15
+    end
16
+  end
17
+end

+ 15
- 2
lib/chervil/parser.rb Voir le fichier

30
     def application
30
     def application
31
       eat(:lparen)
31
       eat(:lparen)
32
 
32
 
33
-      if @current_token.type == :identifier && @current_token.value == 'define'
34
-        return definition
33
+      if @current_token.type == :identifier
34
+        if @current_token.value == 'define'
35
+          return definition
36
+        elsif @current_token.value == 'if'
37
+          return conditional
38
+        end
35
       end
39
       end
36
 
40
 
37
       expression = expr
41
       expression = expr
73
       end
77
       end
74
     end
78
     end
75
 
79
 
80
+    def conditional
81
+      eat(:identifier) # the `if`
82
+      predicate = expr
83
+      true_branch = expr
84
+      false_branch = expr
85
+      eat(:rparen)
86
+      AST::Conditional.new(predicate, true_branch, false_branch)
87
+    end
88
+
76
     def identifier
89
     def identifier
77
       identifier = eat(:identifier)
90
       identifier = eat(:identifier)
78
       AST::Identifier.new(identifier.value)
91
       AST::Identifier.new(identifier.value)

+ 10
- 0
spec/parser_spec.rb Voir le fichier

93
       expect(parse('(+ 1')).to eq(Error.new("Expected rparen but got eof"))
93
       expect(parse('(+ 1')).to eq(Error.new("Expected rparen but got eof"))
94
       expect(parse('1)')).to eq(Error.new("Unexpected token rparen: )"))
94
       expect(parse('1)')).to eq(Error.new("Unexpected token rparen: )"))
95
     end
95
     end
96
+
97
+    it 'parses a conditional' do
98
+      expect(parse('(if #t 1 0)').first).to eq(
99
+        AST::Conditional.new(
100
+          AST::Boolean.new(true),
101
+          AST::Number.new(1.0),
102
+          AST::Number.new(0.0),
103
+        )
104
+      )
105
+    end
96
   end
106
   end
97
 end
107
 end

Chargement…
Annuler
Enregistrer