expression_parser.rb 2.58 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def silence_warnings(&block)
  warn_level = $VERBOSE
  $VERBOSE = nil
  result = block.call
  $VERBOSE = warn_level
  result
end

silence_warnings {
  require 'whittle'
}

undef silence_warnings
module CCS
15
16
17
18
  AssociativityMap = {
    :CCS_LEFT_TO_RIGHT => :left,
    :CCS_RIGHT_TO_LEFT => :right
  }
19
20
21
22
23
24
25
26
27
28
29
  class ExpressionParser < Whittle::Parser
    class << self
      attr_accessor :context
    end
    def initialize(context = nil)
      @context = context
    end
    def parse(*args)
      self.class.context = @context
      super
    end
30

31
32
33
    ExpressionSymbols.reverse_each { |k, v|
      next unless v
      next if k == :CCS_POSITIVE || k == :CCS_NEGATIVE
34
      associativity = AssociativityMap[ExpressionAssociativity[k]]
35
      precedence = ExpressionPrecedence[k]
36
      rule(v) % associativity ^ precedence
37
38
39
40
41
42
43
44
45
    }

    rule(:wsp => /\s+/).skip!
    rule("(")
    rule(")")
    rule("[")
    rule("]")
    rule(",")

Brice Videau's avatar
Brice Videau committed
46
    rule(:none => /none/).as { |b|
47
      Literal::new(value: nil) }
Brice Videau's avatar
Brice Videau committed
48
49
50
51
    rule(:btrue => /true/).as { |b|
      Literal::new(value: true) }
    rule(:bfalse => /false/).as { |b|
      Literal::new(value: false) }
52
53
54
55
56
57
58
59
60
61
    rule(:float => /-?[0-9]+([eE][+-]?[0-9]+|\.[0-9]+([eE][+-]?[0-9]+)?)/).as {|num|
      Literal::new(value: Float(num)) }
    rule(:integer => /-?[0-9]+/).as { |num|
      Literal::new(value: Integer(num)) }
    rule(:identifier => /[a-zA-Z_][a-zA-Z_0-9]*/).as { |identifier|
      Variable::new(hyperparameter: context.hyperparameter_by_name(identifier)) }
    rule(:string => /"([^\0\t\n\r\f"\\]|\\[0tnrf"\\])+"|'([^\0\t\n\r\f'\\]|\\[0tnrf'\\])+'/).as { |str|
      Literal::new(value: eval(str)) }

    rule(:value) do |r|
62
      r[:none]
Brice Videau's avatar
Brice Videau committed
63
64
      r[:btrue]
      r[:bfalse]
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
      r[:string]
      r[:identifier]
      r[:float]
      r[:integer]
    end

    rule(:list_item) do |r|
      r[:list_item, ",", :value].as { |l, _, e| l.push e }
      r[:value].as { |e| [e] }
    end

    rule(:list) do |r|
      r["[", :list_item, "]"].as { |_, l, _| List::new(values: l) }
      r["[", "]"].as { |_, _| List::new(values: []) }
    end

    rule(:expr) do |r|
      r["(", :expr, ")"].as { |_, exp, _| exp }
      ExpressionSymbols.reverse_each { |k, v|
        next unless v
        next if v == "#"
        arity = ExpressionArity[k]
        if arity == 1
88
          r[v, :expr].as { |_, a| Expression.unary(type: k, node: a) }
89
        else
90
          r[:expr, v, :expr].as { |a, _, b| Expression.binary(type: k, left: a, right: b) }
91
92
        end
      }
93
      r[:expr, "#", :list].as { |v, _, l| Expression.binary(type: :CCS_IN, left: v, right: l) }
94
95
96
97
98
99
100
      r[:value]
    end

    start(:expr)
  end

end