Class: Packcr::Node::PredicateNode

Inherits:
Packcr::Node show all
Defined in:
lib/packcr/node/predicate_node.rb,
lib/packcr/generated/node/predicate_node.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Packcr::Node

#alt, #link_references, #reversible?, #seq, #sequence?, #setup, #setup_rule, #verify_captures, #verify_variables

Constructor Details

#initialize(expr = nil, neg = false) ⇒ PredicateNode

Returns a new instance of PredicateNode.



6
7
8
9
10
# File 'lib/packcr/node/predicate_node.rb', line 6

def initialize(expr = nil, neg = false)
  super()
  @expr = expr
  @neg = neg
end

Instance Attribute Details

#exprObject

Returns the value of attribute expr.



4
5
6
# File 'lib/packcr/node/predicate_node.rb', line 4

def expr
  @expr
end

#negObject

Returns the value of attribute neg.



4
5
6
# File 'lib/packcr/node/predicate_node.rb', line 4

def neg
  @neg
end

Instance Method Details

#debug_dump(indent = 0) ⇒ Object



12
13
14
15
16
# File 'lib/packcr/node/predicate_node.rb', line 12

def debug_dump(indent = 0)
  $stdout.print "#{" " * indent}Predicate(neg:#{neg ? 1 : 0}) {\n"
  expr.debug_dump(indent + 2)
  $stdout.print "#{" " * indent}}\n"
end

#generate_code(gen, onfail, indent, unwrap, oncut: nil) ⇒ Object



18
19
20
21
22
23
24
# File 'lib/packcr/node/predicate_node.rb', line 18

def generate_code(gen, onfail, indent, unwrap, oncut: nil)
  if neg
    get_neg_code(gen, onfail, indent, unwrap, oncut)
  else
    get_code(gen, onfail, indent, unwrap, oncut)
  end
end

#get_code(gen, onfail, indent, unwrap, oncut) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/packcr/generated/node/predicate_node.rb', line 4

def get_code(gen, onfail, indent, unwrap, oncut)
  case gen.lang
  when :c
    erbout = +""
    l = gen.next_label
    m = gen.next_label
    r = expr.reachability
    erbout << "{\n    const size_t p = ctx->position_offset;\n".freeze

    if gen.location
      erbout << "    const packcr_location_t p_loc = ctx->position_offset_loc;\n".freeze
    end
    erbout << "#{gen.generate_code(expr, l, 4, false)}".freeze
    if r != Packcr::CODE_REACH__ALWAYS_FAIL
      erbout << "    ctx->position_offset = p;\n".freeze

      if gen.location
        erbout << "    ctx->position_offset_loc = p_loc;\n".freeze
      end
    end
    if r == Packcr::CODE_REACH__BOTH
      erbout << "    goto L#{format("%04d", m)};\n".freeze
    end
    if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
      erbout << "L#{format("%04d", l)}:;\n    ctx->position_offset = p;\n".freeze

      if gen.location
        erbout << "    ctx->position_offset_loc = p_loc;\n".freeze
      end
      erbout << "    goto L#{format("%04d", onfail)};\n".freeze
    end
    if r == Packcr::CODE_REACH__BOTH
      erbout << "L#{format("%04d", m)}:;\n".freeze
    end
    erbout << "}\n".freeze

    erbout
  when :rb
    erbout = +""
    l = gen.next_label
    m = gen.next_label
    r = expr.reachability
    erbout << "catch(#{m}) do\n  pos#{gen.level} = @position_offset\n".freeze

    if gen.location
      erbout << "  p_loc#{gen.level} = @position_offset_pos\n".freeze
    end
    erbout << "  catch(#{l}) do\n#{gen.generate_code(expr, l, 4, false)}".freeze
    if r != Packcr::CODE_REACH__ALWAYS_FAIL
      erbout << "    @position_offset = pos#{gen.level}\n".freeze

      if gen.location
        erbout << "    @position_offset_loc = p_loc#{gen.level}\n".freeze
      end
    end
    if r == Packcr::CODE_REACH__BOTH
      erbout << "    throw(#{m})\n".freeze
    end
    erbout << "  end\n".freeze

    if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
      erbout << "  @position_offset = pos#{gen.level}\n".freeze

      if gen.location
        erbout << "  @position_offset_loc = p_loc#{gen.level}\n".freeze
      end
      erbout << "  throw(#{onfail})\n".freeze
    end
    erbout << "end\n".freeze

    erbout
  else
    raise "unknown lang #{gen.lang}"
  end
end

#get_neg_code(gen, onfail, indent, unwrap, oncut) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/packcr/generated/node/predicate_node.rb', line 80

def get_neg_code(gen, onfail, indent, unwrap, oncut)
  case gen.lang
  when :c
    erbout = +""
    l = gen.next_label
    r = expr.reachability
    erbout << "{\n    const size_t p = ctx->position_offset;\n".freeze

    if gen.location
      erbout << "    const packcr_location_t p_loc = ctx->position_offset_loc;\n".freeze
    end
    erbout << "#{gen.generate_code(expr, l, 4, false)}".freeze
    if r != Packcr::CODE_REACH__ALWAYS_FAIL
      erbout << "    ctx->position_offset = p;\n".freeze

      if gen.location
        erbout << "    ctx->position_offset_loc = p_loc;\n".freeze
      end
      erbout << "    goto L#{format("%04d", onfail)};\n".freeze
    end
    if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
      erbout << "L#{format("%04d", l)}:;\n    ctx->position_offset = p;\n".freeze

      if gen.location
        erbout << "    ctx->position_offset_loc = p_loc;\n".freeze
      end
    end
    erbout << "}\n".freeze

    erbout
  when :rb
    erbout = +""
    l = gen.next_label
    r = expr.reachability
    erbout << "pos#{gen.level} = @position_offset\n".freeze

    if gen.location
      erbout << "p_loc#{gen.level} = @position_offset_loc\n".freeze
    end
    erbout << "catch(#{l}) do\n#{gen.generate_code(expr, l, 2, false)}".freeze
    if r != Packcr::CODE_REACH__ALWAYS_FAIL
      erbout << "  @position_offset = pos#{gen.level}\n".freeze

      if gen.location
        erbout << "  @position_offset_loc = p_loc#{gen.level}\n".freeze
      end
      erbout << "  throw(#{onfail})\n".freeze
    end
    erbout << "end\n".freeze

    if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
      erbout << "@position_offset = pos#{gen.level}\n".freeze

      if gen.location
        erbout << "@position_offset_loc = p_loc#{gen.level}\n".freeze
      end
    end
    erbout
  when :rs
    erbout = +""
    l = gen.next_label
    r = expr.reachability
    erbout << "let p = self.input.position_offset;\n".freeze

    if gen.location
      erbout << "TODO\n".freeze
    end
    erbout << "catch(#{l}, || {\n#{gen.generate_code(expr, l, 4, false)}".freeze
    if r == Packcr::CODE_REACH__ALWAYS_FAIL
      erbout << "    NOP\n".freeze
    else
      erbout << "    self.input.position_offset = p;\n".freeze

      if gen.location
        erbout << "    TODO\n".freeze
      end
      erbout << "    throw(#{onfail})\n".freeze

    end
    erbout << "})?;\n".freeze

    if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
      erbout << "self.input.position_offset = p;\n".freeze

      if gen.location
        erbout << "TODO\n".freeze
      end
    end
    erbout
  else
    raise "unknown lang #{gen.lang}"
  end
end

#nodesObject



34
35
36
# File 'lib/packcr/node/predicate_node.rb', line 34

def nodes
  [expr]
end

#reachabilityObject



26
27
28
29
30
31
32
# File 'lib/packcr/node/predicate_node.rb', line 26

def reachability
  if neg
    -expr.reachability
  else
    expr.reachability
  end
end

#to_hObject



38
39
40
41
42
43
44
# File 'lib/packcr/node/predicate_node.rb', line 38

def to_h
  {
    type: :predicate,
    expr: expr&.to_h,
    neg: neg,
  }
end