trepanning 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/ChangeLog +1279 -235
- data/Makefile +13 -0
- data/NEWS +30 -0
- data/Rakefile +50 -14
- data/app/.gitignore +1 -0
- data/app/breakpoint.rb +7 -2
- data/app/brkptmgr.rb +12 -0
- data/app/cmd_parse.citrus +167 -0
- data/app/cmd_parse.kpeg +221 -0
- data/app/cmd_parse.rb +201 -0
- data/app/cmd_parser.rb +1914 -0
- data/app/complete.rb +79 -0
- data/app/condition.rb +1 -1
- data/app/core.rb +7 -11
- data/app/default.rb +1 -1
- data/app/disassemble.rb +3 -2
- data/app/file.rb +12 -36
- data/app/frame.rb +3 -2
- data/app/irb.rb +9 -5
- data/app/iseq.rb +46 -0
- data/app/options.rb +6 -30
- data/app/run.rb +5 -2
- data/app/util.rb +1 -2
- data/app/yarv.rb +11 -1
- data/bin/.gitignore +1 -0
- data/bin/trepan +6 -6
- data/data/.gitignore +1 -0
- data/interface/.gitignore +1 -0
- data/interface/base_intf.rb +9 -5
- data/interface/comcodes.rb +10 -8
- data/interface/user.rb +76 -17
- data/io/.gitignore +1 -0
- data/io/input.rb +39 -15
- data/io/tcpclient.rb +7 -1
- data/io/tcpfns.rb +5 -3
- data/io/tcpserver.rb +13 -10
- data/lib/.gitignore +1 -0
- data/lib/trepanning.rb +50 -13
- data/processor/.gitignore +1 -0
- data/processor/Makefile +7 -0
- data/processor/breakpoint.rb +7 -2
- data/processor/command/.gitignore +1 -0
- data/processor/command/Makefile +7 -0
- data/processor/command/alias.rb +2 -2
- data/processor/command/backtrace.rb +4 -0
- data/processor/command/base/cmd.rb +45 -2
- data/processor/command/base/subcmd.rb +4 -2
- data/processor/command/base/submgr.rb +23 -19
- data/processor/command/base/subsubcmd.rb +23 -1
- data/processor/command/base/subsubmgr.rb +13 -0
- data/processor/command/break.rb +34 -29
- data/processor/command/complete.rb +37 -0
- data/processor/command/condition.rb +2 -0
- data/processor/command/continue.rb +15 -18
- data/processor/command/disassemble.rb +5 -0
- data/processor/command/down.rb +1 -1
- data/processor/command/eval.rb +70 -0
- data/processor/command/exit.rb +4 -1
- data/processor/command/finish.rb +6 -4
- data/processor/command/frame.rb +6 -3
- data/processor/command/help.rb +97 -54
- data/processor/command/help/.gitignore +1 -0
- data/processor/command/help/README +10 -0
- data/processor/command/help/command.txt +48 -0
- data/processor/command/help/filename.txt +40 -0
- data/processor/command/help/location.txt +37 -0
- data/processor/command/info_subcmd/.gitignore +1 -0
- data/processor/command/info_subcmd/breakpoints.rb +9 -9
- data/processor/command/info_subcmd/{file.rb → files.rb} +92 -27
- data/processor/command/info_subcmd/frame.rb +41 -15
- data/processor/command/info_subcmd/iseq.rb +39 -17
- data/processor/command/info_subcmd/program.rb +2 -8
- data/processor/command/info_subcmd/registers.rb +12 -10
- data/processor/command/info_subcmd/registers_subcmd/.gitignore +1 -0
- data/processor/command/info_subcmd/ruby.rb +60 -0
- data/processor/command/irb.rb +26 -3
- data/processor/command/kill.rb +21 -10
- data/processor/command/list.rb +1 -1
- data/processor/command/macro.rb +37 -23
- data/processor/command/pr.rb +1 -1
- data/processor/command/reload.rb +4 -0
- data/processor/command/reload_subcmd/.gitignore +1 -0
- data/processor/command/restart.rb +9 -9
- data/processor/command/save.rb +29 -36
- data/processor/command/set_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/confirm.rb +23 -0
- data/processor/command/set_subcmd/debug_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/different.rb +2 -0
- data/processor/command/set_subcmd/events.rb +2 -0
- data/processor/command/set_subcmd/max.rb +9 -12
- data/processor/command/set_subcmd/max_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/substitute_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/trace.rb +7 -13
- data/processor/command/set_subcmd/trace_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +12 -27
- data/processor/command/set_subcmd/trace_subcmd/print.rb +10 -8
- data/processor/command/set_subcmd/trace_subcmd/var.rb +6 -10
- data/processor/command/show.rb +12 -1
- data/processor/command/show_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/alias.rb +11 -15
- data/processor/command/show_subcmd/auto_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/basename.rb +1 -9
- data/processor/command/show_subcmd/confirm.rb +25 -0
- data/processor/command/show_subcmd/debug_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/macro.rb +32 -14
- data/processor/command/show_subcmd/max_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/trace_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +11 -31
- data/processor/command/show_subcmd/trace_subcmd/print.rb +4 -20
- data/processor/command/source.rb +7 -1
- data/processor/command/up.rb +7 -4
- data/processor/default.rb +3 -1
- data/processor/eval.rb +13 -0
- data/processor/eventbuf.rb +3 -2
- data/processor/frame.rb +19 -0
- data/processor/help.rb +20 -0
- data/processor/load_cmds.rb +143 -24
- data/processor/location.rb +61 -10
- data/processor/main.rb +30 -11
- data/processor/mock.rb +5 -3
- data/processor/msg.rb +17 -0
- data/processor/running.rb +1 -1
- data/processor/subcmd.rb +3 -2
- data/processor/validate.rb +173 -185
- data/sample/.gitignore +1 -0
- data/sample/list-terminal-colors.rb +139 -0
- data/sample/rocky-dot-trepanrc +14 -0
- data/sample/rocky-trepan-colors.rb +47 -0
- data/test/Makefile +7 -0
- data/test/data/.gitignore +1 -0
- data/test/data/debugger-stop.cmd +3 -0
- data/test/data/debugger-stop.right +5 -0
- data/test/data/fname-with-blank.right +0 -3
- data/test/data/quit.right +0 -1
- data/test/data/quit2.cmd +6 -0
- data/test/data/quit2.right +3 -0
- data/test/data/testing.cmd +1 -0
- data/test/example/.gitignore +1 -0
- data/test/example/debugger-stop.rb +14 -0
- data/test/functional/.gitignore +2 -0
- data/test/functional/fn_helper.rb +7 -9
- data/test/functional/test-break-long.rb +7 -7
- data/test/functional/test-break.rb +7 -7
- data/test/functional/test-condition.rb +4 -4
- data/test/functional/test-delete.rb +6 -5
- data/test/functional/test-eval.rb +115 -0
- data/test/functional/test-raise.rb +1 -1
- data/test/functional/test-return.rb +1 -1
- data/test/integration/.gitignore +2 -0
- data/test/integration/helper.rb +6 -3
- data/test/integration/test-debugger-stop.rb +22 -0
- data/test/integration/test-quit.rb +8 -0
- data/test/unit/.gitignore +1 -0
- data/test/unit/Makefile +7 -0
- data/test/unit/test-app-brkpt.rb +0 -1
- data/test/unit/test-app-cmd_parse.rb +107 -0
- data/test/unit/test-app-cmd_parser.rb +22 -0
- data/test/unit/test-app-complete.rb +38 -0
- data/test/unit/test-app-condition.rb +20 -0
- data/test/unit/test-app-iseq.rb +31 -0
- data/test/unit/test-app-options.rb +9 -1
- data/test/unit/test-app-util.rb +0 -1
- data/test/unit/test-base-cmd.rb +46 -0
- data/test/unit/test-base-subcmd.rb +11 -2
- data/test/unit/test-base-submgr.rb +23 -0
- data/test/unit/test-base-subsubcmd.rb +20 -0
- data/test/unit/test-cmd-break.rb +22 -23
- data/test/unit/test-cmd-help.rb +4 -0
- data/test/unit/test-completion.rb +43 -0
- data/test/unit/test-io-tcpclient.rb +3 -2
- data/test/unit/test-proc-load_cmds.rb +10 -1
- data/test/unit/test-proc-location.rb +39 -0
- data/test/unit/test-proc-main.rb +1 -1
- data/test/unit/test-proc-validate.rb +47 -31
- data/trepanning.gemspec +45 -0
- metadata +247 -179
- data/app/core.rb-consider +0 -198
- data/test/functional/tmp/b3.rb +0 -5
- data/test/functional/tmp/immediate-bug1.rb +0 -9
data/app/cmd_parse.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
# use_grammar.rb
|
2
|
+
require 'rubygems'
|
3
|
+
require_relative 'cmd_parser'
|
4
|
+
|
5
|
+
class Trepan
|
6
|
+
module CmdParser
|
7
|
+
|
8
|
+
# Given a KPeg parse object, return the method of that parse or raise a
|
9
|
+
# Name error if we can't find a method. parent_class is the parent class of
|
10
|
+
# the object we've found so far and "binding" is used if we need
|
11
|
+
# to use eval to find the method.
|
12
|
+
def resolve_method(m, bind, parent_class = nil)
|
13
|
+
name = m.name
|
14
|
+
# DEBUG p name
|
15
|
+
errmsg = nil
|
16
|
+
if m.type == :constant
|
17
|
+
begin
|
18
|
+
if parent_class
|
19
|
+
klass = parent_class.const_get(m.chain[0].name)
|
20
|
+
else
|
21
|
+
errmsg = "Constant #{m} is not a class or module"
|
22
|
+
raise NameError, errmsg unless m.chain[0]
|
23
|
+
klass = eval(m.chain[0].name, bind)
|
24
|
+
end
|
25
|
+
errmsg = "Constant #{klass} is not a class or module" unless
|
26
|
+
raise NameError, errmsg unless
|
27
|
+
klass.kind_of?(Class) or klass.kind_of?(Module)
|
28
|
+
m = m.chain[1]
|
29
|
+
if klass.instance_methods.member?(:binding)
|
30
|
+
bind = klass.bind
|
31
|
+
elsif klass.private_instance_methods.member?(:binding)
|
32
|
+
bind = klass.send(:binding)
|
33
|
+
else
|
34
|
+
bind = nil
|
35
|
+
end
|
36
|
+
resolve_method(m, bind, klass)
|
37
|
+
rescue NameError
|
38
|
+
errmsg ||= "Can't resolve constant #{name}"
|
39
|
+
raise NameError, errmsg
|
40
|
+
end
|
41
|
+
else
|
42
|
+
is_class =
|
43
|
+
begin
|
44
|
+
m.chain && m.chain[0] &&
|
45
|
+
Class == eval("#{m.chain[0].name}.class", bind)
|
46
|
+
rescue
|
47
|
+
false
|
48
|
+
end
|
49
|
+
if is_class
|
50
|
+
# Handles stuff like:
|
51
|
+
# x = File
|
52
|
+
# x.basename
|
53
|
+
# Above, we tested we get a class back when we evalate m.chain[0]
|
54
|
+
# below. So it is safe to run the eval.
|
55
|
+
klass = eval("#{m.chain[0].name}", bind)
|
56
|
+
resolve_method(m.chain[1], klass.send(:binding), klass)
|
57
|
+
else
|
58
|
+
begin
|
59
|
+
errmsg = "Can't get method for #{name.inspect}"
|
60
|
+
if m.chain && m.chain[0]
|
61
|
+
parent_obj = eval("#{m.chain[0].name}", bind) if !parent_class && bind
|
62
|
+
end
|
63
|
+
parent = parent_class || parent_obj
|
64
|
+
meth =
|
65
|
+
if parent
|
66
|
+
errmsg << "in #{parent}"
|
67
|
+
lookup_name = m.chain && m.chain[1] ? m.chain[1].name : name
|
68
|
+
if parent.respond_to?('instance_methods') &&
|
69
|
+
parent.instance_methods.member?(lookup_name.to_sym)
|
70
|
+
parent.instance_method(lookup_name.to_sym)
|
71
|
+
elsif parent.respond_to?('methods')
|
72
|
+
parent.method(lookup_name.to_sym)
|
73
|
+
end
|
74
|
+
elsif m.chain && m.chain[1]
|
75
|
+
eval("#{m.chain[0].name}.method(#{lookup_name.name.inspect})", bind)
|
76
|
+
else
|
77
|
+
eval("self.method(#{name.inspect})", bind)
|
78
|
+
end
|
79
|
+
return meth
|
80
|
+
rescue
|
81
|
+
raise NameError, errmsg
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return the method by evaluating parse_struct.
|
88
|
+
# nil is returned if we can't parse str
|
89
|
+
def meth_for_parse_struct(parse_struct, start_binding)
|
90
|
+
resolve_method(parse_struct, start_binding)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Parse str and return the method associated with that.
|
94
|
+
# nil is returned if we can't parse str
|
95
|
+
def meth_for_string(str, start_binding)
|
96
|
+
@cp ? @cp.setup_parser(str) : @cp = CmdParse.new(str)
|
97
|
+
begin
|
98
|
+
if @cp._class_module_chain
|
99
|
+
# Did we match all of it?
|
100
|
+
if @cp.result.name == str.strip
|
101
|
+
meth_for_parse_struct(@cp.result, start_binding)
|
102
|
+
else
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
else
|
106
|
+
# FIXME: change to raise ParseError?
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
rescue NameError
|
110
|
+
return nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def parse_terminal(terminal_name, loc_str)
|
115
|
+
@cp ? @cp.setup_parser(loc_str) : @cp = CmdParse.new(loc_str)
|
116
|
+
@cp.send(terminal_name) ? @cp : nil
|
117
|
+
end
|
118
|
+
|
119
|
+
def parse_location(loc_str)
|
120
|
+
parse = parse_terminal(:_location, loc_str)
|
121
|
+
parse ? parse.result : nil
|
122
|
+
end
|
123
|
+
|
124
|
+
def parse_breakpoint(str)
|
125
|
+
parse = parse_terminal(:_breakpoint_stmt, str)
|
126
|
+
parse ? parse.result : nil
|
127
|
+
end
|
128
|
+
|
129
|
+
def parse_breakpoint_no_condition(str)
|
130
|
+
parse = parse_terminal(:_breakpoint_stmt_no_condition, str)
|
131
|
+
parse ? parse.result : nil
|
132
|
+
end
|
133
|
+
|
134
|
+
def parse_list(str)
|
135
|
+
parse = parse_terminal(:_list_stmt, str)
|
136
|
+
parse ? parse.result : nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
if __FILE__ == $0
|
142
|
+
# Demo it.
|
143
|
+
%w(a a1 $global __FILE__ Constant 0 1e10 a.b).each do |name|
|
144
|
+
cp = CmdParse.new(name)
|
145
|
+
if cp._identifier && cp.result.name == name
|
146
|
+
p [cp.string, cp.result, 'succeeded']
|
147
|
+
else
|
148
|
+
puts "#{name} failed"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
%w(Object A::B A::B::C A::B::C::D A::B.c A.b.c.d A(5)
|
153
|
+
RubyVM::InstructionSequence.new
|
154
|
+
).each do |name|
|
155
|
+
cp = CmdParse.new(name)
|
156
|
+
if cp._class_module_chain && cp.result.name == name
|
157
|
+
p [cp.string, cp.result, 'succeeded']
|
158
|
+
else
|
159
|
+
puts "#{name} failed"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def five; 5 end
|
164
|
+
include Trepan::CmdParser
|
165
|
+
p meth_for_string('Array.map', binding)
|
166
|
+
p meth_for_string('Rubinius::VM.backtrace', binding)
|
167
|
+
%w(five
|
168
|
+
Array.map
|
169
|
+
RubyVM::InstructionSequence.new
|
170
|
+
Kernel.eval
|
171
|
+
Kernel::eval).each do |str|
|
172
|
+
meth = meth_for_string(str, binding)
|
173
|
+
p meth
|
174
|
+
end
|
175
|
+
module Testing
|
176
|
+
def testing; 5 end
|
177
|
+
module_function :testing
|
178
|
+
end
|
179
|
+
p meth_for_string('Testing.testing', binding)
|
180
|
+
p meth_for_string('File.basename', binding)
|
181
|
+
x = File
|
182
|
+
p meth_for_string('x.basename', binding)
|
183
|
+
def x.five; 5; end
|
184
|
+
p meth_for_string('x.five', binding)
|
185
|
+
p x.five
|
186
|
+
|
187
|
+
p parse_terminal(:_line_number, '5').result
|
188
|
+
p parse_terminal(:_vm_offset, '@5').result
|
189
|
+
|
190
|
+
# Location stuff
|
191
|
+
['fn', 'fn 5', 'fn @5', '@5', '5'].each do |location|
|
192
|
+
p parse_location(location)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Location stuff
|
196
|
+
['fn if a > b', 'fn 5 unless c > d', 'fn:5 if x', '@5', '5'].each do |str|
|
197
|
+
p parse_breakpoint(str)
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
data/app/cmd_parser.rb
ADDED
@@ -0,0 +1,1914 @@
|
|
1
|
+
class CmdParse
|
2
|
+
# STANDALONE START
|
3
|
+
def setup_parser(str, debug=false)
|
4
|
+
@string = str
|
5
|
+
@pos = 0
|
6
|
+
@memoizations = Hash.new { |h,k| h[k] = {} }
|
7
|
+
@result = nil
|
8
|
+
@failed_rule = nil
|
9
|
+
@failing_rule_offset = -1
|
10
|
+
end
|
11
|
+
|
12
|
+
# This is distinct from setup_parser so that a standalone parser
|
13
|
+
# can redefine #initialize and still have access to the proper
|
14
|
+
# parser setup code.
|
15
|
+
#
|
16
|
+
def initialize(str, debug=false)
|
17
|
+
setup_parser(str, debug)
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :string
|
21
|
+
attr_reader :result, :failing_rule_offset
|
22
|
+
attr_accessor :pos
|
23
|
+
|
24
|
+
# STANDALONE START
|
25
|
+
def current_column(target=pos)
|
26
|
+
if c = string.rindex("\n", target-1)
|
27
|
+
return target - c - 1
|
28
|
+
end
|
29
|
+
|
30
|
+
target + 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def current_line(target=pos)
|
34
|
+
cur_offset = 0
|
35
|
+
cur_line = 0
|
36
|
+
|
37
|
+
string.each_line do |line|
|
38
|
+
cur_line += 1
|
39
|
+
cur_offset += line.size
|
40
|
+
return cur_line if cur_offset >= target
|
41
|
+
end
|
42
|
+
|
43
|
+
-1
|
44
|
+
end
|
45
|
+
|
46
|
+
def lines
|
47
|
+
lines = []
|
48
|
+
string.each_line { |l| lines << l }
|
49
|
+
lines
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
|
54
|
+
def get_text(start)
|
55
|
+
@string[start..@pos-1]
|
56
|
+
end
|
57
|
+
|
58
|
+
def show_pos
|
59
|
+
width = 10
|
60
|
+
if @pos < width
|
61
|
+
"#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
|
62
|
+
else
|
63
|
+
"#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def failure_info
|
68
|
+
l = current_line @failing_rule_offset
|
69
|
+
c = current_column @failing_rule_offset
|
70
|
+
info = self.class::Rules[@failed_rule]
|
71
|
+
|
72
|
+
"line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
|
73
|
+
end
|
74
|
+
|
75
|
+
def failure_caret
|
76
|
+
l = current_line @failing_rule_offset
|
77
|
+
c = current_column @failing_rule_offset
|
78
|
+
|
79
|
+
line = lines[l-1]
|
80
|
+
"#{line}\n#{' ' * (c - 1)}^"
|
81
|
+
end
|
82
|
+
|
83
|
+
def failure_character
|
84
|
+
l = current_line @failing_rule_offset
|
85
|
+
c = current_column @failing_rule_offset
|
86
|
+
lines[l-1][c-1, 1]
|
87
|
+
end
|
88
|
+
|
89
|
+
def failure_oneline
|
90
|
+
l = current_line @failing_rule_offset
|
91
|
+
c = current_column @failing_rule_offset
|
92
|
+
|
93
|
+
info = self.class::Rules[@failed_rule]
|
94
|
+
char = lines[l-1][c-1, 1]
|
95
|
+
|
96
|
+
"@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
|
97
|
+
end
|
98
|
+
|
99
|
+
class ParseError < RuntimeError
|
100
|
+
end
|
101
|
+
|
102
|
+
def raise_error
|
103
|
+
raise ParseError, failure_oneline
|
104
|
+
end
|
105
|
+
|
106
|
+
def show_error(io=STDOUT)
|
107
|
+
error_pos = @failing_rule_offset
|
108
|
+
line_no = current_line(error_pos)
|
109
|
+
col_no = current_column(error_pos)
|
110
|
+
|
111
|
+
info = self.class::Rules[@failed_rule]
|
112
|
+
io.puts "On line #{line_no}, column #{col_no}:"
|
113
|
+
io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
|
114
|
+
io.puts "Got: #{string[error_pos,1].inspect}"
|
115
|
+
line = lines[line_no-1]
|
116
|
+
io.puts "=> #{line}"
|
117
|
+
io.print(" " * (col_no + 3))
|
118
|
+
io.puts "^"
|
119
|
+
end
|
120
|
+
|
121
|
+
def set_failed_rule(name)
|
122
|
+
if @pos > @failing_rule_offset
|
123
|
+
@failed_rule = name
|
124
|
+
@failing_rule_offset = @pos
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
attr_reader :failed_rule
|
129
|
+
|
130
|
+
def match_string(str)
|
131
|
+
len = str.size
|
132
|
+
if @string[pos,len] == str
|
133
|
+
@pos += len
|
134
|
+
return str
|
135
|
+
end
|
136
|
+
|
137
|
+
return nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def scan(reg)
|
141
|
+
if m = reg.match(@string[@pos..-1])
|
142
|
+
width = m.end(0)
|
143
|
+
@pos += width
|
144
|
+
return true
|
145
|
+
end
|
146
|
+
|
147
|
+
return nil
|
148
|
+
end
|
149
|
+
|
150
|
+
if "".respond_to? :getbyte
|
151
|
+
def get_byte
|
152
|
+
if @pos >= @string.size
|
153
|
+
return nil
|
154
|
+
end
|
155
|
+
|
156
|
+
s = @string.getbyte @pos
|
157
|
+
@pos += 1
|
158
|
+
s
|
159
|
+
end
|
160
|
+
else
|
161
|
+
def get_byte
|
162
|
+
if @pos >= @string.size
|
163
|
+
return nil
|
164
|
+
end
|
165
|
+
|
166
|
+
s = @string[@pos]
|
167
|
+
@pos += 1
|
168
|
+
s
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def parse
|
173
|
+
_root ? true : false
|
174
|
+
end
|
175
|
+
|
176
|
+
class LeftRecursive
|
177
|
+
def initialize(detected=false)
|
178
|
+
@detected = detected
|
179
|
+
end
|
180
|
+
|
181
|
+
attr_accessor :detected
|
182
|
+
end
|
183
|
+
|
184
|
+
class MemoEntry
|
185
|
+
def initialize(ans, pos)
|
186
|
+
@ans = ans
|
187
|
+
@pos = pos
|
188
|
+
@uses = 1
|
189
|
+
@result = nil
|
190
|
+
end
|
191
|
+
|
192
|
+
attr_reader :ans, :pos, :uses, :result
|
193
|
+
|
194
|
+
def inc!
|
195
|
+
@uses += 1
|
196
|
+
end
|
197
|
+
|
198
|
+
def move!(ans, pos, result)
|
199
|
+
@ans = ans
|
200
|
+
@pos = pos
|
201
|
+
@result = result
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def apply(rule)
|
206
|
+
if m = @memoizations[rule][@pos]
|
207
|
+
m.inc!
|
208
|
+
|
209
|
+
prev = @pos
|
210
|
+
@pos = m.pos
|
211
|
+
if m.ans.kind_of? LeftRecursive
|
212
|
+
m.ans.detected = true
|
213
|
+
return nil
|
214
|
+
end
|
215
|
+
|
216
|
+
@result = m.result
|
217
|
+
|
218
|
+
return m.ans
|
219
|
+
else
|
220
|
+
lr = LeftRecursive.new(false)
|
221
|
+
m = MemoEntry.new(lr, @pos)
|
222
|
+
@memoizations[rule][@pos] = m
|
223
|
+
start_pos = @pos
|
224
|
+
|
225
|
+
ans = __send__ rule
|
226
|
+
|
227
|
+
m.move! ans, @pos, @result
|
228
|
+
|
229
|
+
# Don't bother trying to grow the left recursion
|
230
|
+
# if it's failing straight away (thus there is no seed)
|
231
|
+
if ans and lr.detected
|
232
|
+
return grow_lr(rule, start_pos, m)
|
233
|
+
else
|
234
|
+
return ans
|
235
|
+
end
|
236
|
+
|
237
|
+
return ans
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def grow_lr(rule, start_pos, m)
|
242
|
+
while true
|
243
|
+
@pos = start_pos
|
244
|
+
@result = m.result
|
245
|
+
|
246
|
+
ans = __send__ rule
|
247
|
+
return nil unless ans
|
248
|
+
|
249
|
+
break if @pos <= m.pos
|
250
|
+
|
251
|
+
m.move! ans, @pos, @result
|
252
|
+
end
|
253
|
+
|
254
|
+
@result = m.result
|
255
|
+
@pos = m.pos
|
256
|
+
return m.ans
|
257
|
+
end
|
258
|
+
|
259
|
+
class RuleInfo
|
260
|
+
def initialize(name, rendered)
|
261
|
+
@name = name
|
262
|
+
@rendered = rendered
|
263
|
+
end
|
264
|
+
|
265
|
+
attr_reader :name, :rendered
|
266
|
+
end
|
267
|
+
|
268
|
+
def self.rule_info(name, rendered)
|
269
|
+
RuleInfo.new(name, rendered)
|
270
|
+
end
|
271
|
+
|
272
|
+
#
|
273
|
+
|
274
|
+
|
275
|
+
#####################################################
|
276
|
+
# Structure to hold composite method names
|
277
|
+
SymbolEntry = Struct.new(:type, :name, :chain)
|
278
|
+
|
279
|
+
|
280
|
+
# Structure to hold position information
|
281
|
+
Position = Struct.new(:container_type, :container,
|
282
|
+
:position_type, :position)
|
283
|
+
|
284
|
+
# Structure to hold breakpoint information
|
285
|
+
Breakpoint = Struct.new(:position, :negate, :condition)
|
286
|
+
|
287
|
+
# Structure to hold list information
|
288
|
+
List = Struct.new(:position, :num)
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
# upcase_letter = /[A-Z]/
|
294
|
+
def _upcase_letter
|
295
|
+
_tmp = scan(/\A(?-mix:[A-Z])/)
|
296
|
+
set_failed_rule :_upcase_letter unless _tmp
|
297
|
+
return _tmp
|
298
|
+
end
|
299
|
+
|
300
|
+
# downcase_letter = /[a-z]/
|
301
|
+
def _downcase_letter
|
302
|
+
_tmp = scan(/\A(?-mix:[a-z])/)
|
303
|
+
set_failed_rule :_downcase_letter unless _tmp
|
304
|
+
return _tmp
|
305
|
+
end
|
306
|
+
|
307
|
+
# suffix_letter = /[=!?]/
|
308
|
+
def _suffix_letter
|
309
|
+
_tmp = scan(/\A(?-mix:[=!?])/)
|
310
|
+
set_failed_rule :_suffix_letter unless _tmp
|
311
|
+
return _tmp
|
312
|
+
end
|
313
|
+
|
314
|
+
# letter = (upcase_letter | downcase_letter)
|
315
|
+
def _letter
|
316
|
+
|
317
|
+
_save = self.pos
|
318
|
+
while true # choice
|
319
|
+
_tmp = apply(:_upcase_letter)
|
320
|
+
break if _tmp
|
321
|
+
self.pos = _save
|
322
|
+
_tmp = apply(:_downcase_letter)
|
323
|
+
break if _tmp
|
324
|
+
self.pos = _save
|
325
|
+
break
|
326
|
+
end # end choice
|
327
|
+
|
328
|
+
set_failed_rule :_letter unless _tmp
|
329
|
+
return _tmp
|
330
|
+
end
|
331
|
+
|
332
|
+
# id_symbol = (letter | "_" | [0-9])
|
333
|
+
def _id_symbol
|
334
|
+
|
335
|
+
_save = self.pos
|
336
|
+
while true # choice
|
337
|
+
_tmp = apply(:_letter)
|
338
|
+
break if _tmp
|
339
|
+
self.pos = _save
|
340
|
+
_tmp = match_string("_")
|
341
|
+
break if _tmp
|
342
|
+
self.pos = _save
|
343
|
+
_save1 = self.pos
|
344
|
+
_tmp = get_byte
|
345
|
+
if _tmp
|
346
|
+
unless _tmp >= 48 and _tmp <= 57
|
347
|
+
self.pos = _save1
|
348
|
+
_tmp = nil
|
349
|
+
end
|
350
|
+
end
|
351
|
+
break if _tmp
|
352
|
+
self.pos = _save
|
353
|
+
break
|
354
|
+
end # end choice
|
355
|
+
|
356
|
+
set_failed_rule :_id_symbol unless _tmp
|
357
|
+
return _tmp
|
358
|
+
end
|
359
|
+
|
360
|
+
# vm_identifier = < (downcase_letter | "_") id_symbol* suffix_letter? > { SymbolEntry.new(:variable, text) }
|
361
|
+
def _vm_identifier
|
362
|
+
|
363
|
+
_save = self.pos
|
364
|
+
while true # sequence
|
365
|
+
_text_start = self.pos
|
366
|
+
|
367
|
+
_save1 = self.pos
|
368
|
+
while true # sequence
|
369
|
+
|
370
|
+
_save2 = self.pos
|
371
|
+
while true # choice
|
372
|
+
_tmp = apply(:_downcase_letter)
|
373
|
+
break if _tmp
|
374
|
+
self.pos = _save2
|
375
|
+
_tmp = match_string("_")
|
376
|
+
break if _tmp
|
377
|
+
self.pos = _save2
|
378
|
+
break
|
379
|
+
end # end choice
|
380
|
+
|
381
|
+
unless _tmp
|
382
|
+
self.pos = _save1
|
383
|
+
break
|
384
|
+
end
|
385
|
+
while true
|
386
|
+
_tmp = apply(:_id_symbol)
|
387
|
+
break unless _tmp
|
388
|
+
end
|
389
|
+
_tmp = true
|
390
|
+
unless _tmp
|
391
|
+
self.pos = _save1
|
392
|
+
break
|
393
|
+
end
|
394
|
+
_save4 = self.pos
|
395
|
+
_tmp = apply(:_suffix_letter)
|
396
|
+
unless _tmp
|
397
|
+
_tmp = true
|
398
|
+
self.pos = _save4
|
399
|
+
end
|
400
|
+
unless _tmp
|
401
|
+
self.pos = _save1
|
402
|
+
end
|
403
|
+
break
|
404
|
+
end # end sequence
|
405
|
+
|
406
|
+
if _tmp
|
407
|
+
text = get_text(_text_start)
|
408
|
+
end
|
409
|
+
unless _tmp
|
410
|
+
self.pos = _save
|
411
|
+
break
|
412
|
+
end
|
413
|
+
@result = begin;
|
414
|
+
SymbolEntry.new(:variable, text)
|
415
|
+
; end
|
416
|
+
_tmp = true
|
417
|
+
unless _tmp
|
418
|
+
self.pos = _save
|
419
|
+
end
|
420
|
+
break
|
421
|
+
end # end sequence
|
422
|
+
|
423
|
+
set_failed_rule :_vm_identifier unless _tmp
|
424
|
+
return _tmp
|
425
|
+
end
|
426
|
+
|
427
|
+
# variable_identifier = < (downcase_letter | "_") id_symbol* > { SymbolEntry.new(:variable, text) }
|
428
|
+
def _variable_identifier
|
429
|
+
|
430
|
+
_save = self.pos
|
431
|
+
while true # sequence
|
432
|
+
_text_start = self.pos
|
433
|
+
|
434
|
+
_save1 = self.pos
|
435
|
+
while true # sequence
|
436
|
+
|
437
|
+
_save2 = self.pos
|
438
|
+
while true # choice
|
439
|
+
_tmp = apply(:_downcase_letter)
|
440
|
+
break if _tmp
|
441
|
+
self.pos = _save2
|
442
|
+
_tmp = match_string("_")
|
443
|
+
break if _tmp
|
444
|
+
self.pos = _save2
|
445
|
+
break
|
446
|
+
end # end choice
|
447
|
+
|
448
|
+
unless _tmp
|
449
|
+
self.pos = _save1
|
450
|
+
break
|
451
|
+
end
|
452
|
+
while true
|
453
|
+
_tmp = apply(:_id_symbol)
|
454
|
+
break unless _tmp
|
455
|
+
end
|
456
|
+
_tmp = true
|
457
|
+
unless _tmp
|
458
|
+
self.pos = _save1
|
459
|
+
end
|
460
|
+
break
|
461
|
+
end # end sequence
|
462
|
+
|
463
|
+
if _tmp
|
464
|
+
text = get_text(_text_start)
|
465
|
+
end
|
466
|
+
unless _tmp
|
467
|
+
self.pos = _save
|
468
|
+
break
|
469
|
+
end
|
470
|
+
@result = begin;
|
471
|
+
SymbolEntry.new(:variable, text)
|
472
|
+
; end
|
473
|
+
_tmp = true
|
474
|
+
unless _tmp
|
475
|
+
self.pos = _save
|
476
|
+
end
|
477
|
+
break
|
478
|
+
end # end sequence
|
479
|
+
|
480
|
+
set_failed_rule :_variable_identifier unless _tmp
|
481
|
+
return _tmp
|
482
|
+
end
|
483
|
+
|
484
|
+
# constant_identifier = < upcase_letter id_symbol* > { SymbolEntry.new(:constant, text) }
|
485
|
+
def _constant_identifier
|
486
|
+
|
487
|
+
_save = self.pos
|
488
|
+
while true # sequence
|
489
|
+
_text_start = self.pos
|
490
|
+
|
491
|
+
_save1 = self.pos
|
492
|
+
while true # sequence
|
493
|
+
_tmp = apply(:_upcase_letter)
|
494
|
+
unless _tmp
|
495
|
+
self.pos = _save1
|
496
|
+
break
|
497
|
+
end
|
498
|
+
while true
|
499
|
+
_tmp = apply(:_id_symbol)
|
500
|
+
break unless _tmp
|
501
|
+
end
|
502
|
+
_tmp = true
|
503
|
+
unless _tmp
|
504
|
+
self.pos = _save1
|
505
|
+
end
|
506
|
+
break
|
507
|
+
end # end sequence
|
508
|
+
|
509
|
+
if _tmp
|
510
|
+
text = get_text(_text_start)
|
511
|
+
end
|
512
|
+
unless _tmp
|
513
|
+
self.pos = _save
|
514
|
+
break
|
515
|
+
end
|
516
|
+
@result = begin;
|
517
|
+
SymbolEntry.new(:constant, text)
|
518
|
+
; end
|
519
|
+
_tmp = true
|
520
|
+
unless _tmp
|
521
|
+
self.pos = _save
|
522
|
+
end
|
523
|
+
break
|
524
|
+
end # end sequence
|
525
|
+
|
526
|
+
set_failed_rule :_constant_identifier unless _tmp
|
527
|
+
return _tmp
|
528
|
+
end
|
529
|
+
|
530
|
+
# global_identifier = < "$" (constant_identifier | variable_identifier) > { SymbolEntry.new(:global, text) }
|
531
|
+
def _global_identifier
|
532
|
+
|
533
|
+
_save = self.pos
|
534
|
+
while true # sequence
|
535
|
+
_text_start = self.pos
|
536
|
+
|
537
|
+
_save1 = self.pos
|
538
|
+
while true # sequence
|
539
|
+
_tmp = match_string("$")
|
540
|
+
unless _tmp
|
541
|
+
self.pos = _save1
|
542
|
+
break
|
543
|
+
end
|
544
|
+
|
545
|
+
_save2 = self.pos
|
546
|
+
while true # choice
|
547
|
+
_tmp = apply(:_constant_identifier)
|
548
|
+
break if _tmp
|
549
|
+
self.pos = _save2
|
550
|
+
_tmp = apply(:_variable_identifier)
|
551
|
+
break if _tmp
|
552
|
+
self.pos = _save2
|
553
|
+
break
|
554
|
+
end # end choice
|
555
|
+
|
556
|
+
unless _tmp
|
557
|
+
self.pos = _save1
|
558
|
+
end
|
559
|
+
break
|
560
|
+
end # end sequence
|
561
|
+
|
562
|
+
if _tmp
|
563
|
+
text = get_text(_text_start)
|
564
|
+
end
|
565
|
+
unless _tmp
|
566
|
+
self.pos = _save
|
567
|
+
break
|
568
|
+
end
|
569
|
+
@result = begin;
|
570
|
+
SymbolEntry.new(:global, text)
|
571
|
+
; end
|
572
|
+
_tmp = true
|
573
|
+
unless _tmp
|
574
|
+
self.pos = _save
|
575
|
+
end
|
576
|
+
break
|
577
|
+
end # end sequence
|
578
|
+
|
579
|
+
set_failed_rule :_global_identifier unless _tmp
|
580
|
+
return _tmp
|
581
|
+
end
|
582
|
+
|
583
|
+
# local_internal_identifier = (constant_identifier | variable_identifier)
|
584
|
+
def _local_internal_identifier
|
585
|
+
|
586
|
+
_save = self.pos
|
587
|
+
while true # choice
|
588
|
+
_tmp = apply(:_constant_identifier)
|
589
|
+
break if _tmp
|
590
|
+
self.pos = _save
|
591
|
+
_tmp = apply(:_variable_identifier)
|
592
|
+
break if _tmp
|
593
|
+
self.pos = _save
|
594
|
+
break
|
595
|
+
end # end choice
|
596
|
+
|
597
|
+
set_failed_rule :_local_internal_identifier unless _tmp
|
598
|
+
return _tmp
|
599
|
+
end
|
600
|
+
|
601
|
+
# local_identifier = (constant_identifier | vm_identifier)
|
602
|
+
def _local_identifier
|
603
|
+
|
604
|
+
_save = self.pos
|
605
|
+
while true # choice
|
606
|
+
_tmp = apply(:_constant_identifier)
|
607
|
+
break if _tmp
|
608
|
+
self.pos = _save
|
609
|
+
_tmp = apply(:_vm_identifier)
|
610
|
+
break if _tmp
|
611
|
+
self.pos = _save
|
612
|
+
break
|
613
|
+
end # end choice
|
614
|
+
|
615
|
+
set_failed_rule :_local_identifier unless _tmp
|
616
|
+
return _tmp
|
617
|
+
end
|
618
|
+
|
619
|
+
# instance_identifier = < "@" local_identifier > { SymbolEntry.new(:instance, text) }
|
620
|
+
def _instance_identifier
|
621
|
+
|
622
|
+
_save = self.pos
|
623
|
+
while true # sequence
|
624
|
+
_text_start = self.pos
|
625
|
+
|
626
|
+
_save1 = self.pos
|
627
|
+
while true # sequence
|
628
|
+
_tmp = match_string("@")
|
629
|
+
unless _tmp
|
630
|
+
self.pos = _save1
|
631
|
+
break
|
632
|
+
end
|
633
|
+
_tmp = apply(:_local_identifier)
|
634
|
+
unless _tmp
|
635
|
+
self.pos = _save1
|
636
|
+
end
|
637
|
+
break
|
638
|
+
end # end sequence
|
639
|
+
|
640
|
+
if _tmp
|
641
|
+
text = get_text(_text_start)
|
642
|
+
end
|
643
|
+
unless _tmp
|
644
|
+
self.pos = _save
|
645
|
+
break
|
646
|
+
end
|
647
|
+
@result = begin;
|
648
|
+
SymbolEntry.new(:instance, text)
|
649
|
+
; end
|
650
|
+
_tmp = true
|
651
|
+
unless _tmp
|
652
|
+
self.pos = _save
|
653
|
+
end
|
654
|
+
break
|
655
|
+
end # end sequence
|
656
|
+
|
657
|
+
set_failed_rule :_instance_identifier unless _tmp
|
658
|
+
return _tmp
|
659
|
+
end
|
660
|
+
|
661
|
+
# classvar_identifier = "@@" local_identifier:id { SymbolEntry.new(:classvar, id) }
|
662
|
+
def _classvar_identifier
|
663
|
+
|
664
|
+
_save = self.pos
|
665
|
+
while true # sequence
|
666
|
+
_tmp = match_string("@@")
|
667
|
+
unless _tmp
|
668
|
+
self.pos = _save
|
669
|
+
break
|
670
|
+
end
|
671
|
+
_tmp = apply(:_local_identifier)
|
672
|
+
id = @result
|
673
|
+
unless _tmp
|
674
|
+
self.pos = _save
|
675
|
+
break
|
676
|
+
end
|
677
|
+
@result = begin;
|
678
|
+
SymbolEntry.new(:classvar, id)
|
679
|
+
; end
|
680
|
+
_tmp = true
|
681
|
+
unless _tmp
|
682
|
+
self.pos = _save
|
683
|
+
end
|
684
|
+
break
|
685
|
+
end # end sequence
|
686
|
+
|
687
|
+
set_failed_rule :_classvar_identifier unless _tmp
|
688
|
+
return _tmp
|
689
|
+
end
|
690
|
+
|
691
|
+
# identifier = (global_identifier | instance_identifier | classvar_identifier | local_identifier)
|
692
|
+
def _identifier
|
693
|
+
|
694
|
+
_save = self.pos
|
695
|
+
while true # choice
|
696
|
+
_tmp = apply(:_global_identifier)
|
697
|
+
break if _tmp
|
698
|
+
self.pos = _save
|
699
|
+
_tmp = apply(:_instance_identifier)
|
700
|
+
break if _tmp
|
701
|
+
self.pos = _save
|
702
|
+
_tmp = apply(:_classvar_identifier)
|
703
|
+
break if _tmp
|
704
|
+
self.pos = _save
|
705
|
+
_tmp = apply(:_local_identifier)
|
706
|
+
break if _tmp
|
707
|
+
self.pos = _save
|
708
|
+
break
|
709
|
+
end # end choice
|
710
|
+
|
711
|
+
set_failed_rule :_identifier unless _tmp
|
712
|
+
return _tmp
|
713
|
+
end
|
714
|
+
|
715
|
+
# id_separator = < ("::" | ".") > { text }
|
716
|
+
def _id_separator
|
717
|
+
|
718
|
+
_save = self.pos
|
719
|
+
while true # sequence
|
720
|
+
_text_start = self.pos
|
721
|
+
|
722
|
+
_save1 = self.pos
|
723
|
+
while true # choice
|
724
|
+
_tmp = match_string("::")
|
725
|
+
break if _tmp
|
726
|
+
self.pos = _save1
|
727
|
+
_tmp = match_string(".")
|
728
|
+
break if _tmp
|
729
|
+
self.pos = _save1
|
730
|
+
break
|
731
|
+
end # end choice
|
732
|
+
|
733
|
+
if _tmp
|
734
|
+
text = get_text(_text_start)
|
735
|
+
end
|
736
|
+
unless _tmp
|
737
|
+
self.pos = _save
|
738
|
+
break
|
739
|
+
end
|
740
|
+
@result = begin; text ; end
|
741
|
+
_tmp = true
|
742
|
+
unless _tmp
|
743
|
+
self.pos = _save
|
744
|
+
end
|
745
|
+
break
|
746
|
+
end # end sequence
|
747
|
+
|
748
|
+
set_failed_rule :_id_separator unless _tmp
|
749
|
+
return _tmp
|
750
|
+
end
|
751
|
+
|
752
|
+
# internal_class_module_chain = (< local_internal_identifier:parent id_separator:sep internal_class_module_chain:child > { SymbolEntry.new(parent.type, text, [parent, child, sep]) } | local_identifier)
|
753
|
+
def _internal_class_module_chain
|
754
|
+
|
755
|
+
_save = self.pos
|
756
|
+
while true # choice
|
757
|
+
|
758
|
+
_save1 = self.pos
|
759
|
+
while true # sequence
|
760
|
+
_text_start = self.pos
|
761
|
+
|
762
|
+
_save2 = self.pos
|
763
|
+
while true # sequence
|
764
|
+
_tmp = apply(:_local_internal_identifier)
|
765
|
+
parent = @result
|
766
|
+
unless _tmp
|
767
|
+
self.pos = _save2
|
768
|
+
break
|
769
|
+
end
|
770
|
+
_tmp = apply(:_id_separator)
|
771
|
+
sep = @result
|
772
|
+
unless _tmp
|
773
|
+
self.pos = _save2
|
774
|
+
break
|
775
|
+
end
|
776
|
+
_tmp = apply(:_internal_class_module_chain)
|
777
|
+
child = @result
|
778
|
+
unless _tmp
|
779
|
+
self.pos = _save2
|
780
|
+
end
|
781
|
+
break
|
782
|
+
end # end sequence
|
783
|
+
|
784
|
+
if _tmp
|
785
|
+
text = get_text(_text_start)
|
786
|
+
end
|
787
|
+
unless _tmp
|
788
|
+
self.pos = _save1
|
789
|
+
break
|
790
|
+
end
|
791
|
+
@result = begin;
|
792
|
+
SymbolEntry.new(parent.type, text, [parent, child, sep])
|
793
|
+
; end
|
794
|
+
_tmp = true
|
795
|
+
unless _tmp
|
796
|
+
self.pos = _save1
|
797
|
+
end
|
798
|
+
break
|
799
|
+
end # end sequence
|
800
|
+
|
801
|
+
break if _tmp
|
802
|
+
self.pos = _save
|
803
|
+
_tmp = apply(:_local_identifier)
|
804
|
+
break if _tmp
|
805
|
+
self.pos = _save
|
806
|
+
break
|
807
|
+
end # end choice
|
808
|
+
|
809
|
+
set_failed_rule :_internal_class_module_chain unless _tmp
|
810
|
+
return _tmp
|
811
|
+
end
|
812
|
+
|
813
|
+
# class_module_chain = (< identifier:parent id_separator:sep internal_class_module_chain:child > { SymbolEntry.new(parent.type, text, [parent, child, sep]) } | identifier)
|
814
|
+
def _class_module_chain
|
815
|
+
|
816
|
+
_save = self.pos
|
817
|
+
while true # choice
|
818
|
+
|
819
|
+
_save1 = self.pos
|
820
|
+
while true # sequence
|
821
|
+
_text_start = self.pos
|
822
|
+
|
823
|
+
_save2 = self.pos
|
824
|
+
while true # sequence
|
825
|
+
_tmp = apply(:_identifier)
|
826
|
+
parent = @result
|
827
|
+
unless _tmp
|
828
|
+
self.pos = _save2
|
829
|
+
break
|
830
|
+
end
|
831
|
+
_tmp = apply(:_id_separator)
|
832
|
+
sep = @result
|
833
|
+
unless _tmp
|
834
|
+
self.pos = _save2
|
835
|
+
break
|
836
|
+
end
|
837
|
+
_tmp = apply(:_internal_class_module_chain)
|
838
|
+
child = @result
|
839
|
+
unless _tmp
|
840
|
+
self.pos = _save2
|
841
|
+
end
|
842
|
+
break
|
843
|
+
end # end sequence
|
844
|
+
|
845
|
+
if _tmp
|
846
|
+
text = get_text(_text_start)
|
847
|
+
end
|
848
|
+
unless _tmp
|
849
|
+
self.pos = _save1
|
850
|
+
break
|
851
|
+
end
|
852
|
+
@result = begin;
|
853
|
+
SymbolEntry.new(parent.type, text, [parent, child, sep])
|
854
|
+
; end
|
855
|
+
_tmp = true
|
856
|
+
unless _tmp
|
857
|
+
self.pos = _save1
|
858
|
+
end
|
859
|
+
break
|
860
|
+
end # end sequence
|
861
|
+
|
862
|
+
break if _tmp
|
863
|
+
self.pos = _save
|
864
|
+
_tmp = apply(:_identifier)
|
865
|
+
break if _tmp
|
866
|
+
self.pos = _save
|
867
|
+
break
|
868
|
+
end # end choice
|
869
|
+
|
870
|
+
set_failed_rule :_class_module_chain unless _tmp
|
871
|
+
return _tmp
|
872
|
+
end
|
873
|
+
|
874
|
+
# sp = /[ \t]/
|
875
|
+
def _sp
|
876
|
+
_tmp = scan(/\A(?-mix:[ \t])/)
|
877
|
+
set_failed_rule :_sp unless _tmp
|
878
|
+
return _tmp
|
879
|
+
end
|
880
|
+
|
881
|
+
# - = sp+
|
882
|
+
def __hyphen_
|
883
|
+
_save = self.pos
|
884
|
+
_tmp = apply(:_sp)
|
885
|
+
if _tmp
|
886
|
+
while true
|
887
|
+
_tmp = apply(:_sp)
|
888
|
+
break unless _tmp
|
889
|
+
end
|
890
|
+
_tmp = true
|
891
|
+
else
|
892
|
+
self.pos = _save
|
893
|
+
end
|
894
|
+
set_failed_rule :__hyphen_ unless _tmp
|
895
|
+
return _tmp
|
896
|
+
end
|
897
|
+
|
898
|
+
# dbl_escapes = ("\\\"" { '"' } | "\\n" { "\n" } | "\\t" { "\t" } | "\\\\" { "\\" })
|
899
|
+
def _dbl_escapes
|
900
|
+
|
901
|
+
_save = self.pos
|
902
|
+
while true # choice
|
903
|
+
|
904
|
+
_save1 = self.pos
|
905
|
+
while true # sequence
|
906
|
+
_tmp = match_string("\\\"")
|
907
|
+
unless _tmp
|
908
|
+
self.pos = _save1
|
909
|
+
break
|
910
|
+
end
|
911
|
+
@result = begin; '"' ; end
|
912
|
+
_tmp = true
|
913
|
+
unless _tmp
|
914
|
+
self.pos = _save1
|
915
|
+
end
|
916
|
+
break
|
917
|
+
end # end sequence
|
918
|
+
|
919
|
+
break if _tmp
|
920
|
+
self.pos = _save
|
921
|
+
|
922
|
+
_save2 = self.pos
|
923
|
+
while true # sequence
|
924
|
+
_tmp = match_string("\\n")
|
925
|
+
unless _tmp
|
926
|
+
self.pos = _save2
|
927
|
+
break
|
928
|
+
end
|
929
|
+
@result = begin; "\n" ; end
|
930
|
+
_tmp = true
|
931
|
+
unless _tmp
|
932
|
+
self.pos = _save2
|
933
|
+
end
|
934
|
+
break
|
935
|
+
end # end sequence
|
936
|
+
|
937
|
+
break if _tmp
|
938
|
+
self.pos = _save
|
939
|
+
|
940
|
+
_save3 = self.pos
|
941
|
+
while true # sequence
|
942
|
+
_tmp = match_string("\\t")
|
943
|
+
unless _tmp
|
944
|
+
self.pos = _save3
|
945
|
+
break
|
946
|
+
end
|
947
|
+
@result = begin; "\t" ; end
|
948
|
+
_tmp = true
|
949
|
+
unless _tmp
|
950
|
+
self.pos = _save3
|
951
|
+
end
|
952
|
+
break
|
953
|
+
end # end sequence
|
954
|
+
|
955
|
+
break if _tmp
|
956
|
+
self.pos = _save
|
957
|
+
|
958
|
+
_save4 = self.pos
|
959
|
+
while true # sequence
|
960
|
+
_tmp = match_string("\\\\")
|
961
|
+
unless _tmp
|
962
|
+
self.pos = _save4
|
963
|
+
break
|
964
|
+
end
|
965
|
+
@result = begin; "\\" ; end
|
966
|
+
_tmp = true
|
967
|
+
unless _tmp
|
968
|
+
self.pos = _save4
|
969
|
+
end
|
970
|
+
break
|
971
|
+
end # end sequence
|
972
|
+
|
973
|
+
break if _tmp
|
974
|
+
self.pos = _save
|
975
|
+
break
|
976
|
+
end # end choice
|
977
|
+
|
978
|
+
set_failed_rule :_dbl_escapes unless _tmp
|
979
|
+
return _tmp
|
980
|
+
end
|
981
|
+
|
982
|
+
# escapes = ("\\\"" { '"' } | "\\n" { "\n" } | "\\t" { "\t" } | "\\ " { " " } | "\\:" { ":" } | "\\\\" { "\\" })
|
983
|
+
def _escapes
|
984
|
+
|
985
|
+
_save = self.pos
|
986
|
+
while true # choice
|
987
|
+
|
988
|
+
_save1 = self.pos
|
989
|
+
while true # sequence
|
990
|
+
_tmp = match_string("\\\"")
|
991
|
+
unless _tmp
|
992
|
+
self.pos = _save1
|
993
|
+
break
|
994
|
+
end
|
995
|
+
@result = begin; '"' ; end
|
996
|
+
_tmp = true
|
997
|
+
unless _tmp
|
998
|
+
self.pos = _save1
|
999
|
+
end
|
1000
|
+
break
|
1001
|
+
end # end sequence
|
1002
|
+
|
1003
|
+
break if _tmp
|
1004
|
+
self.pos = _save
|
1005
|
+
|
1006
|
+
_save2 = self.pos
|
1007
|
+
while true # sequence
|
1008
|
+
_tmp = match_string("\\n")
|
1009
|
+
unless _tmp
|
1010
|
+
self.pos = _save2
|
1011
|
+
break
|
1012
|
+
end
|
1013
|
+
@result = begin; "\n" ; end
|
1014
|
+
_tmp = true
|
1015
|
+
unless _tmp
|
1016
|
+
self.pos = _save2
|
1017
|
+
end
|
1018
|
+
break
|
1019
|
+
end # end sequence
|
1020
|
+
|
1021
|
+
break if _tmp
|
1022
|
+
self.pos = _save
|
1023
|
+
|
1024
|
+
_save3 = self.pos
|
1025
|
+
while true # sequence
|
1026
|
+
_tmp = match_string("\\t")
|
1027
|
+
unless _tmp
|
1028
|
+
self.pos = _save3
|
1029
|
+
break
|
1030
|
+
end
|
1031
|
+
@result = begin; "\t" ; end
|
1032
|
+
_tmp = true
|
1033
|
+
unless _tmp
|
1034
|
+
self.pos = _save3
|
1035
|
+
end
|
1036
|
+
break
|
1037
|
+
end # end sequence
|
1038
|
+
|
1039
|
+
break if _tmp
|
1040
|
+
self.pos = _save
|
1041
|
+
|
1042
|
+
_save4 = self.pos
|
1043
|
+
while true # sequence
|
1044
|
+
_tmp = match_string("\\ ")
|
1045
|
+
unless _tmp
|
1046
|
+
self.pos = _save4
|
1047
|
+
break
|
1048
|
+
end
|
1049
|
+
@result = begin; " " ; end
|
1050
|
+
_tmp = true
|
1051
|
+
unless _tmp
|
1052
|
+
self.pos = _save4
|
1053
|
+
end
|
1054
|
+
break
|
1055
|
+
end # end sequence
|
1056
|
+
|
1057
|
+
break if _tmp
|
1058
|
+
self.pos = _save
|
1059
|
+
|
1060
|
+
_save5 = self.pos
|
1061
|
+
while true # sequence
|
1062
|
+
_tmp = match_string("\\:")
|
1063
|
+
unless _tmp
|
1064
|
+
self.pos = _save5
|
1065
|
+
break
|
1066
|
+
end
|
1067
|
+
@result = begin; ":" ; end
|
1068
|
+
_tmp = true
|
1069
|
+
unless _tmp
|
1070
|
+
self.pos = _save5
|
1071
|
+
end
|
1072
|
+
break
|
1073
|
+
end # end sequence
|
1074
|
+
|
1075
|
+
break if _tmp
|
1076
|
+
self.pos = _save
|
1077
|
+
|
1078
|
+
_save6 = self.pos
|
1079
|
+
while true # sequence
|
1080
|
+
_tmp = match_string("\\\\")
|
1081
|
+
unless _tmp
|
1082
|
+
self.pos = _save6
|
1083
|
+
break
|
1084
|
+
end
|
1085
|
+
@result = begin; "\\" ; end
|
1086
|
+
_tmp = true
|
1087
|
+
unless _tmp
|
1088
|
+
self.pos = _save6
|
1089
|
+
end
|
1090
|
+
break
|
1091
|
+
end # end sequence
|
1092
|
+
|
1093
|
+
break if _tmp
|
1094
|
+
self.pos = _save
|
1095
|
+
break
|
1096
|
+
end # end choice
|
1097
|
+
|
1098
|
+
set_failed_rule :_escapes unless _tmp
|
1099
|
+
return _tmp
|
1100
|
+
end
|
1101
|
+
|
1102
|
+
# dbl_seq = < /[^\\"]+/ > { text }
|
1103
|
+
def _dbl_seq
|
1104
|
+
|
1105
|
+
_save = self.pos
|
1106
|
+
while true # sequence
|
1107
|
+
_text_start = self.pos
|
1108
|
+
_tmp = scan(/\A(?-mix:[^\\"]+)/)
|
1109
|
+
if _tmp
|
1110
|
+
text = get_text(_text_start)
|
1111
|
+
end
|
1112
|
+
unless _tmp
|
1113
|
+
self.pos = _save
|
1114
|
+
break
|
1115
|
+
end
|
1116
|
+
@result = begin; text ; end
|
1117
|
+
_tmp = true
|
1118
|
+
unless _tmp
|
1119
|
+
self.pos = _save
|
1120
|
+
end
|
1121
|
+
break
|
1122
|
+
end # end sequence
|
1123
|
+
|
1124
|
+
set_failed_rule :_dbl_seq unless _tmp
|
1125
|
+
return _tmp
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
# dbl_not_quote = (dbl_escapes | dbl_seq)+:ary { ary }
|
1129
|
+
def _dbl_not_quote
|
1130
|
+
|
1131
|
+
_save = self.pos
|
1132
|
+
while true # sequence
|
1133
|
+
_save1 = self.pos
|
1134
|
+
_ary = []
|
1135
|
+
|
1136
|
+
_save2 = self.pos
|
1137
|
+
while true # choice
|
1138
|
+
_tmp = apply(:_dbl_escapes)
|
1139
|
+
break if _tmp
|
1140
|
+
self.pos = _save2
|
1141
|
+
_tmp = apply(:_dbl_seq)
|
1142
|
+
break if _tmp
|
1143
|
+
self.pos = _save2
|
1144
|
+
break
|
1145
|
+
end # end choice
|
1146
|
+
|
1147
|
+
if _tmp
|
1148
|
+
_ary << @result
|
1149
|
+
while true
|
1150
|
+
|
1151
|
+
_save3 = self.pos
|
1152
|
+
while true # choice
|
1153
|
+
_tmp = apply(:_dbl_escapes)
|
1154
|
+
break if _tmp
|
1155
|
+
self.pos = _save3
|
1156
|
+
_tmp = apply(:_dbl_seq)
|
1157
|
+
break if _tmp
|
1158
|
+
self.pos = _save3
|
1159
|
+
break
|
1160
|
+
end # end choice
|
1161
|
+
|
1162
|
+
_ary << @result if _tmp
|
1163
|
+
break unless _tmp
|
1164
|
+
end
|
1165
|
+
_tmp = true
|
1166
|
+
@result = _ary
|
1167
|
+
else
|
1168
|
+
self.pos = _save1
|
1169
|
+
end
|
1170
|
+
ary = @result
|
1171
|
+
unless _tmp
|
1172
|
+
self.pos = _save
|
1173
|
+
break
|
1174
|
+
end
|
1175
|
+
@result = begin; ary ; end
|
1176
|
+
_tmp = true
|
1177
|
+
unless _tmp
|
1178
|
+
self.pos = _save
|
1179
|
+
end
|
1180
|
+
break
|
1181
|
+
end # end sequence
|
1182
|
+
|
1183
|
+
set_failed_rule :_dbl_not_quote unless _tmp
|
1184
|
+
return _tmp
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
# dbl_string = "\"" dbl_not_quote:ary "\"" { ary.join }
|
1188
|
+
def _dbl_string
|
1189
|
+
|
1190
|
+
_save = self.pos
|
1191
|
+
while true # sequence
|
1192
|
+
_tmp = match_string("\"")
|
1193
|
+
unless _tmp
|
1194
|
+
self.pos = _save
|
1195
|
+
break
|
1196
|
+
end
|
1197
|
+
_tmp = apply(:_dbl_not_quote)
|
1198
|
+
ary = @result
|
1199
|
+
unless _tmp
|
1200
|
+
self.pos = _save
|
1201
|
+
break
|
1202
|
+
end
|
1203
|
+
_tmp = match_string("\"")
|
1204
|
+
unless _tmp
|
1205
|
+
self.pos = _save
|
1206
|
+
break
|
1207
|
+
end
|
1208
|
+
@result = begin; ary.join ; end
|
1209
|
+
_tmp = true
|
1210
|
+
unless _tmp
|
1211
|
+
self.pos = _save
|
1212
|
+
end
|
1213
|
+
break
|
1214
|
+
end # end sequence
|
1215
|
+
|
1216
|
+
set_failed_rule :_dbl_string unless _tmp
|
1217
|
+
return _tmp
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
# not_space_colon = (escapes | < /[^ \t\n:]/ > { text })
|
1221
|
+
def _not_space_colon
|
1222
|
+
|
1223
|
+
_save = self.pos
|
1224
|
+
while true # choice
|
1225
|
+
_tmp = apply(:_escapes)
|
1226
|
+
break if _tmp
|
1227
|
+
self.pos = _save
|
1228
|
+
|
1229
|
+
_save1 = self.pos
|
1230
|
+
while true # sequence
|
1231
|
+
_text_start = self.pos
|
1232
|
+
_tmp = scan(/\A(?-mix:[^ \t\n:])/)
|
1233
|
+
if _tmp
|
1234
|
+
text = get_text(_text_start)
|
1235
|
+
end
|
1236
|
+
unless _tmp
|
1237
|
+
self.pos = _save1
|
1238
|
+
break
|
1239
|
+
end
|
1240
|
+
@result = begin; text ; end
|
1241
|
+
_tmp = true
|
1242
|
+
unless _tmp
|
1243
|
+
self.pos = _save1
|
1244
|
+
end
|
1245
|
+
break
|
1246
|
+
end # end sequence
|
1247
|
+
|
1248
|
+
break if _tmp
|
1249
|
+
self.pos = _save
|
1250
|
+
break
|
1251
|
+
end # end choice
|
1252
|
+
|
1253
|
+
set_failed_rule :_not_space_colon unless _tmp
|
1254
|
+
return _tmp
|
1255
|
+
end
|
1256
|
+
|
1257
|
+
# not_space_colons = not_space_colon+:ary { ary.join }
|
1258
|
+
def _not_space_colons
|
1259
|
+
|
1260
|
+
_save = self.pos
|
1261
|
+
while true # sequence
|
1262
|
+
_save1 = self.pos
|
1263
|
+
_ary = []
|
1264
|
+
_tmp = apply(:_not_space_colon)
|
1265
|
+
if _tmp
|
1266
|
+
_ary << @result
|
1267
|
+
while true
|
1268
|
+
_tmp = apply(:_not_space_colon)
|
1269
|
+
_ary << @result if _tmp
|
1270
|
+
break unless _tmp
|
1271
|
+
end
|
1272
|
+
_tmp = true
|
1273
|
+
@result = _ary
|
1274
|
+
else
|
1275
|
+
self.pos = _save1
|
1276
|
+
end
|
1277
|
+
ary = @result
|
1278
|
+
unless _tmp
|
1279
|
+
self.pos = _save
|
1280
|
+
break
|
1281
|
+
end
|
1282
|
+
@result = begin; ary.join ; end
|
1283
|
+
_tmp = true
|
1284
|
+
unless _tmp
|
1285
|
+
self.pos = _save
|
1286
|
+
end
|
1287
|
+
break
|
1288
|
+
end # end sequence
|
1289
|
+
|
1290
|
+
set_failed_rule :_not_space_colons unless _tmp
|
1291
|
+
return _tmp
|
1292
|
+
end
|
1293
|
+
|
1294
|
+
# filename = (dbl_string | not_space_colons)
|
1295
|
+
def _filename
|
1296
|
+
|
1297
|
+
_save = self.pos
|
1298
|
+
while true # choice
|
1299
|
+
_tmp = apply(:_dbl_string)
|
1300
|
+
break if _tmp
|
1301
|
+
self.pos = _save
|
1302
|
+
_tmp = apply(:_not_space_colons)
|
1303
|
+
break if _tmp
|
1304
|
+
self.pos = _save
|
1305
|
+
break
|
1306
|
+
end # end choice
|
1307
|
+
|
1308
|
+
set_failed_rule :_filename unless _tmp
|
1309
|
+
return _tmp
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
# file_pos_sep = (sp+ | ":")
|
1313
|
+
def _file_pos_sep
|
1314
|
+
|
1315
|
+
_save = self.pos
|
1316
|
+
while true # choice
|
1317
|
+
_save1 = self.pos
|
1318
|
+
_tmp = apply(:_sp)
|
1319
|
+
if _tmp
|
1320
|
+
while true
|
1321
|
+
_tmp = apply(:_sp)
|
1322
|
+
break unless _tmp
|
1323
|
+
end
|
1324
|
+
_tmp = true
|
1325
|
+
else
|
1326
|
+
self.pos = _save1
|
1327
|
+
end
|
1328
|
+
break if _tmp
|
1329
|
+
self.pos = _save
|
1330
|
+
_tmp = match_string(":")
|
1331
|
+
break if _tmp
|
1332
|
+
self.pos = _save
|
1333
|
+
break
|
1334
|
+
end # end choice
|
1335
|
+
|
1336
|
+
set_failed_rule :_file_pos_sep unless _tmp
|
1337
|
+
return _tmp
|
1338
|
+
end
|
1339
|
+
|
1340
|
+
# integer = < /[0-9]+/ > { text.to_i }
|
1341
|
+
def _integer
|
1342
|
+
|
1343
|
+
_save = self.pos
|
1344
|
+
while true # sequence
|
1345
|
+
_text_start = self.pos
|
1346
|
+
_tmp = scan(/\A(?-mix:[0-9]+)/)
|
1347
|
+
if _tmp
|
1348
|
+
text = get_text(_text_start)
|
1349
|
+
end
|
1350
|
+
unless _tmp
|
1351
|
+
self.pos = _save
|
1352
|
+
break
|
1353
|
+
end
|
1354
|
+
@result = begin; text.to_i ; end
|
1355
|
+
_tmp = true
|
1356
|
+
unless _tmp
|
1357
|
+
self.pos = _save
|
1358
|
+
end
|
1359
|
+
break
|
1360
|
+
end # end sequence
|
1361
|
+
|
1362
|
+
set_failed_rule :_integer unless _tmp
|
1363
|
+
return _tmp
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
# line_number = integer
|
1367
|
+
def _line_number
|
1368
|
+
_tmp = apply(:_integer)
|
1369
|
+
set_failed_rule :_line_number unless _tmp
|
1370
|
+
return _tmp
|
1371
|
+
end
|
1372
|
+
|
1373
|
+
# vm_offset = "@" integer:int { Position.new(nil, nil, :offset, int) }
|
1374
|
+
def _vm_offset
|
1375
|
+
|
1376
|
+
_save = self.pos
|
1377
|
+
while true # sequence
|
1378
|
+
_tmp = match_string("@")
|
1379
|
+
unless _tmp
|
1380
|
+
self.pos = _save
|
1381
|
+
break
|
1382
|
+
end
|
1383
|
+
_tmp = apply(:_integer)
|
1384
|
+
int = @result
|
1385
|
+
unless _tmp
|
1386
|
+
self.pos = _save
|
1387
|
+
break
|
1388
|
+
end
|
1389
|
+
@result = begin;
|
1390
|
+
Position.new(nil, nil, :offset, int)
|
1391
|
+
; end
|
1392
|
+
_tmp = true
|
1393
|
+
unless _tmp
|
1394
|
+
self.pos = _save
|
1395
|
+
end
|
1396
|
+
break
|
1397
|
+
end # end sequence
|
1398
|
+
|
1399
|
+
set_failed_rule :_vm_offset unless _tmp
|
1400
|
+
return _tmp
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
# position = (vm_offset | line_number:l { Position.new(nil, nil, :line, l) })
|
1404
|
+
def _position
|
1405
|
+
|
1406
|
+
_save = self.pos
|
1407
|
+
while true # choice
|
1408
|
+
_tmp = apply(:_vm_offset)
|
1409
|
+
break if _tmp
|
1410
|
+
self.pos = _save
|
1411
|
+
|
1412
|
+
_save1 = self.pos
|
1413
|
+
while true # sequence
|
1414
|
+
_tmp = apply(:_line_number)
|
1415
|
+
l = @result
|
1416
|
+
unless _tmp
|
1417
|
+
self.pos = _save1
|
1418
|
+
break
|
1419
|
+
end
|
1420
|
+
@result = begin;
|
1421
|
+
Position.new(nil, nil, :line, l)
|
1422
|
+
; end
|
1423
|
+
_tmp = true
|
1424
|
+
unless _tmp
|
1425
|
+
self.pos = _save1
|
1426
|
+
end
|
1427
|
+
break
|
1428
|
+
end # end sequence
|
1429
|
+
|
1430
|
+
break if _tmp
|
1431
|
+
self.pos = _save
|
1432
|
+
break
|
1433
|
+
end # end choice
|
1434
|
+
|
1435
|
+
set_failed_rule :_position unless _tmp
|
1436
|
+
return _tmp
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
# location = (position | < filename >:file &{ File.exist?(file) } file_pos_sep position:pos { Position.new(:file, file, pos.position_type, pos.position) } | < filename >:file &{ File.exist?(file) } { Position.new(:file, file, nil, nil) } | class_module_chain?:fn file_pos_sep position:pos { Position.new(:fn, fn, pos.position_type, pos.position) } | class_module_chain?:fn { Position.new(:fn, fn, nil, nil) })
|
1440
|
+
def _location
|
1441
|
+
|
1442
|
+
_save = self.pos
|
1443
|
+
while true # choice
|
1444
|
+
_tmp = apply(:_position)
|
1445
|
+
break if _tmp
|
1446
|
+
self.pos = _save
|
1447
|
+
|
1448
|
+
_save1 = self.pos
|
1449
|
+
while true # sequence
|
1450
|
+
_text_start = self.pos
|
1451
|
+
_tmp = apply(:_filename)
|
1452
|
+
if _tmp
|
1453
|
+
text = get_text(_text_start)
|
1454
|
+
end
|
1455
|
+
file = @result
|
1456
|
+
unless _tmp
|
1457
|
+
self.pos = _save1
|
1458
|
+
break
|
1459
|
+
end
|
1460
|
+
_save2 = self.pos
|
1461
|
+
_tmp = begin; File.exist?(file) ; end
|
1462
|
+
self.pos = _save2
|
1463
|
+
unless _tmp
|
1464
|
+
self.pos = _save1
|
1465
|
+
break
|
1466
|
+
end
|
1467
|
+
_tmp = apply(:_file_pos_sep)
|
1468
|
+
unless _tmp
|
1469
|
+
self.pos = _save1
|
1470
|
+
break
|
1471
|
+
end
|
1472
|
+
_tmp = apply(:_position)
|
1473
|
+
pos = @result
|
1474
|
+
unless _tmp
|
1475
|
+
self.pos = _save1
|
1476
|
+
break
|
1477
|
+
end
|
1478
|
+
@result = begin;
|
1479
|
+
Position.new(:file, file, pos.position_type, pos.position)
|
1480
|
+
; end
|
1481
|
+
_tmp = true
|
1482
|
+
unless _tmp
|
1483
|
+
self.pos = _save1
|
1484
|
+
end
|
1485
|
+
break
|
1486
|
+
end # end sequence
|
1487
|
+
|
1488
|
+
break if _tmp
|
1489
|
+
self.pos = _save
|
1490
|
+
|
1491
|
+
_save3 = self.pos
|
1492
|
+
while true # sequence
|
1493
|
+
_text_start = self.pos
|
1494
|
+
_tmp = apply(:_filename)
|
1495
|
+
if _tmp
|
1496
|
+
text = get_text(_text_start)
|
1497
|
+
end
|
1498
|
+
file = @result
|
1499
|
+
unless _tmp
|
1500
|
+
self.pos = _save3
|
1501
|
+
break
|
1502
|
+
end
|
1503
|
+
_save4 = self.pos
|
1504
|
+
_tmp = begin; File.exist?(file) ; end
|
1505
|
+
self.pos = _save4
|
1506
|
+
unless _tmp
|
1507
|
+
self.pos = _save3
|
1508
|
+
break
|
1509
|
+
end
|
1510
|
+
@result = begin;
|
1511
|
+
Position.new(:file, file, nil, nil)
|
1512
|
+
; end
|
1513
|
+
_tmp = true
|
1514
|
+
unless _tmp
|
1515
|
+
self.pos = _save3
|
1516
|
+
end
|
1517
|
+
break
|
1518
|
+
end # end sequence
|
1519
|
+
|
1520
|
+
break if _tmp
|
1521
|
+
self.pos = _save
|
1522
|
+
|
1523
|
+
_save5 = self.pos
|
1524
|
+
while true # sequence
|
1525
|
+
_save6 = self.pos
|
1526
|
+
_tmp = apply(:_class_module_chain)
|
1527
|
+
@result = nil unless _tmp
|
1528
|
+
unless _tmp
|
1529
|
+
_tmp = true
|
1530
|
+
self.pos = _save6
|
1531
|
+
end
|
1532
|
+
fn = @result
|
1533
|
+
unless _tmp
|
1534
|
+
self.pos = _save5
|
1535
|
+
break
|
1536
|
+
end
|
1537
|
+
_tmp = apply(:_file_pos_sep)
|
1538
|
+
unless _tmp
|
1539
|
+
self.pos = _save5
|
1540
|
+
break
|
1541
|
+
end
|
1542
|
+
_tmp = apply(:_position)
|
1543
|
+
pos = @result
|
1544
|
+
unless _tmp
|
1545
|
+
self.pos = _save5
|
1546
|
+
break
|
1547
|
+
end
|
1548
|
+
@result = begin;
|
1549
|
+
Position.new(:fn, fn, pos.position_type, pos.position)
|
1550
|
+
; end
|
1551
|
+
_tmp = true
|
1552
|
+
unless _tmp
|
1553
|
+
self.pos = _save5
|
1554
|
+
end
|
1555
|
+
break
|
1556
|
+
end # end sequence
|
1557
|
+
|
1558
|
+
break if _tmp
|
1559
|
+
self.pos = _save
|
1560
|
+
|
1561
|
+
_save7 = self.pos
|
1562
|
+
while true # sequence
|
1563
|
+
_save8 = self.pos
|
1564
|
+
_tmp = apply(:_class_module_chain)
|
1565
|
+
@result = nil unless _tmp
|
1566
|
+
unless _tmp
|
1567
|
+
_tmp = true
|
1568
|
+
self.pos = _save8
|
1569
|
+
end
|
1570
|
+
fn = @result
|
1571
|
+
unless _tmp
|
1572
|
+
self.pos = _save7
|
1573
|
+
break
|
1574
|
+
end
|
1575
|
+
@result = begin;
|
1576
|
+
Position.new(:fn, fn, nil, nil)
|
1577
|
+
; end
|
1578
|
+
_tmp = true
|
1579
|
+
unless _tmp
|
1580
|
+
self.pos = _save7
|
1581
|
+
end
|
1582
|
+
break
|
1583
|
+
end # end sequence
|
1584
|
+
|
1585
|
+
break if _tmp
|
1586
|
+
self.pos = _save
|
1587
|
+
break
|
1588
|
+
end # end choice
|
1589
|
+
|
1590
|
+
set_failed_rule :_location unless _tmp
|
1591
|
+
return _tmp
|
1592
|
+
end
|
1593
|
+
|
1594
|
+
# if_unless = < ("if" | "unless") > { text }
|
1595
|
+
def _if_unless
|
1596
|
+
|
1597
|
+
_save = self.pos
|
1598
|
+
while true # sequence
|
1599
|
+
_text_start = self.pos
|
1600
|
+
|
1601
|
+
_save1 = self.pos
|
1602
|
+
while true # choice
|
1603
|
+
_tmp = match_string("if")
|
1604
|
+
break if _tmp
|
1605
|
+
self.pos = _save1
|
1606
|
+
_tmp = match_string("unless")
|
1607
|
+
break if _tmp
|
1608
|
+
self.pos = _save1
|
1609
|
+
break
|
1610
|
+
end # end choice
|
1611
|
+
|
1612
|
+
if _tmp
|
1613
|
+
text = get_text(_text_start)
|
1614
|
+
end
|
1615
|
+
unless _tmp
|
1616
|
+
self.pos = _save
|
1617
|
+
break
|
1618
|
+
end
|
1619
|
+
@result = begin; text ; end
|
1620
|
+
_tmp = true
|
1621
|
+
unless _tmp
|
1622
|
+
self.pos = _save
|
1623
|
+
end
|
1624
|
+
break
|
1625
|
+
end # end sequence
|
1626
|
+
|
1627
|
+
set_failed_rule :_if_unless unless _tmp
|
1628
|
+
return _tmp
|
1629
|
+
end
|
1630
|
+
|
1631
|
+
# condition = < /.+/ > { text}
|
1632
|
+
def _condition
|
1633
|
+
|
1634
|
+
_save = self.pos
|
1635
|
+
while true # sequence
|
1636
|
+
_text_start = self.pos
|
1637
|
+
_tmp = scan(/\A(?-mix:.+)/)
|
1638
|
+
if _tmp
|
1639
|
+
text = get_text(_text_start)
|
1640
|
+
end
|
1641
|
+
unless _tmp
|
1642
|
+
self.pos = _save
|
1643
|
+
break
|
1644
|
+
end
|
1645
|
+
@result = begin; text; end
|
1646
|
+
_tmp = true
|
1647
|
+
unless _tmp
|
1648
|
+
self.pos = _save
|
1649
|
+
end
|
1650
|
+
break
|
1651
|
+
end # end sequence
|
1652
|
+
|
1653
|
+
set_failed_rule :_condition unless _tmp
|
1654
|
+
return _tmp
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
# breakpoint_stmt_no_condition = location:loc { Breakpoint.new(loc, false, 'true') }
|
1658
|
+
def _breakpoint_stmt_no_condition
|
1659
|
+
|
1660
|
+
_save = self.pos
|
1661
|
+
while true # sequence
|
1662
|
+
_tmp = apply(:_location)
|
1663
|
+
loc = @result
|
1664
|
+
unless _tmp
|
1665
|
+
self.pos = _save
|
1666
|
+
break
|
1667
|
+
end
|
1668
|
+
@result = begin;
|
1669
|
+
Breakpoint.new(loc, false, 'true')
|
1670
|
+
; end
|
1671
|
+
_tmp = true
|
1672
|
+
unless _tmp
|
1673
|
+
self.pos = _save
|
1674
|
+
end
|
1675
|
+
break
|
1676
|
+
end # end sequence
|
1677
|
+
|
1678
|
+
set_failed_rule :_breakpoint_stmt_no_condition unless _tmp
|
1679
|
+
return _tmp
|
1680
|
+
end
|
1681
|
+
|
1682
|
+
# breakpoint_stmt = (location:loc - if_unless:iu - condition:cond { Breakpoint.new(loc, iu == 'unless', cond) } | breakpoint_stmt_no_condition)
|
1683
|
+
def _breakpoint_stmt
|
1684
|
+
|
1685
|
+
_save = self.pos
|
1686
|
+
while true # choice
|
1687
|
+
|
1688
|
+
_save1 = self.pos
|
1689
|
+
while true # sequence
|
1690
|
+
_tmp = apply(:_location)
|
1691
|
+
loc = @result
|
1692
|
+
unless _tmp
|
1693
|
+
self.pos = _save1
|
1694
|
+
break
|
1695
|
+
end
|
1696
|
+
_tmp = apply(:__hyphen_)
|
1697
|
+
unless _tmp
|
1698
|
+
self.pos = _save1
|
1699
|
+
break
|
1700
|
+
end
|
1701
|
+
_tmp = apply(:_if_unless)
|
1702
|
+
iu = @result
|
1703
|
+
unless _tmp
|
1704
|
+
self.pos = _save1
|
1705
|
+
break
|
1706
|
+
end
|
1707
|
+
_tmp = apply(:__hyphen_)
|
1708
|
+
unless _tmp
|
1709
|
+
self.pos = _save1
|
1710
|
+
break
|
1711
|
+
end
|
1712
|
+
_tmp = apply(:_condition)
|
1713
|
+
cond = @result
|
1714
|
+
unless _tmp
|
1715
|
+
self.pos = _save1
|
1716
|
+
break
|
1717
|
+
end
|
1718
|
+
@result = begin;
|
1719
|
+
Breakpoint.new(loc, iu == 'unless', cond)
|
1720
|
+
; end
|
1721
|
+
_tmp = true
|
1722
|
+
unless _tmp
|
1723
|
+
self.pos = _save1
|
1724
|
+
end
|
1725
|
+
break
|
1726
|
+
end # end sequence
|
1727
|
+
|
1728
|
+
break if _tmp
|
1729
|
+
self.pos = _save
|
1730
|
+
_tmp = apply(:_breakpoint_stmt_no_condition)
|
1731
|
+
break if _tmp
|
1732
|
+
self.pos = _save
|
1733
|
+
break
|
1734
|
+
end # end choice
|
1735
|
+
|
1736
|
+
set_failed_rule :_breakpoint_stmt unless _tmp
|
1737
|
+
return _tmp
|
1738
|
+
end
|
1739
|
+
|
1740
|
+
# list_special_targets = < "." "-" > { text }
|
1741
|
+
def _list_special_targets
|
1742
|
+
|
1743
|
+
_save = self.pos
|
1744
|
+
while true # sequence
|
1745
|
+
_text_start = self.pos
|
1746
|
+
|
1747
|
+
_save1 = self.pos
|
1748
|
+
while true # sequence
|
1749
|
+
_tmp = match_string(".")
|
1750
|
+
unless _tmp
|
1751
|
+
self.pos = _save1
|
1752
|
+
break
|
1753
|
+
end
|
1754
|
+
_tmp = match_string("-")
|
1755
|
+
unless _tmp
|
1756
|
+
self.pos = _save1
|
1757
|
+
end
|
1758
|
+
break
|
1759
|
+
end # end sequence
|
1760
|
+
|
1761
|
+
if _tmp
|
1762
|
+
text = get_text(_text_start)
|
1763
|
+
end
|
1764
|
+
unless _tmp
|
1765
|
+
self.pos = _save
|
1766
|
+
break
|
1767
|
+
end
|
1768
|
+
@result = begin; text ; end
|
1769
|
+
_tmp = true
|
1770
|
+
unless _tmp
|
1771
|
+
self.pos = _save
|
1772
|
+
end
|
1773
|
+
break
|
1774
|
+
end # end sequence
|
1775
|
+
|
1776
|
+
set_failed_rule :_list_special_targets unless _tmp
|
1777
|
+
return _tmp
|
1778
|
+
end
|
1779
|
+
|
1780
|
+
# list_stmt = (list_special_target | location):loc - integer:int? { List.new(loc, int) }
|
1781
|
+
def _list_stmt
|
1782
|
+
|
1783
|
+
_save = self.pos
|
1784
|
+
while true # sequence
|
1785
|
+
|
1786
|
+
_save1 = self.pos
|
1787
|
+
while true # choice
|
1788
|
+
_tmp = apply(:_list_special_target)
|
1789
|
+
break if _tmp
|
1790
|
+
self.pos = _save1
|
1791
|
+
_tmp = apply(:_location)
|
1792
|
+
break if _tmp
|
1793
|
+
self.pos = _save1
|
1794
|
+
break
|
1795
|
+
end # end choice
|
1796
|
+
|
1797
|
+
loc = @result
|
1798
|
+
unless _tmp
|
1799
|
+
self.pos = _save
|
1800
|
+
break
|
1801
|
+
end
|
1802
|
+
_tmp = apply(:__hyphen_)
|
1803
|
+
unless _tmp
|
1804
|
+
self.pos = _save
|
1805
|
+
break
|
1806
|
+
end
|
1807
|
+
_save2 = self.pos
|
1808
|
+
_tmp = apply(:_integer)
|
1809
|
+
int = @result
|
1810
|
+
unless _tmp
|
1811
|
+
_tmp = true
|
1812
|
+
self.pos = _save2
|
1813
|
+
end
|
1814
|
+
unless _tmp
|
1815
|
+
self.pos = _save
|
1816
|
+
break
|
1817
|
+
end
|
1818
|
+
@result = begin;
|
1819
|
+
List.new(loc, int)
|
1820
|
+
; end
|
1821
|
+
_tmp = true
|
1822
|
+
unless _tmp
|
1823
|
+
self.pos = _save
|
1824
|
+
end
|
1825
|
+
break
|
1826
|
+
end # end sequence
|
1827
|
+
|
1828
|
+
set_failed_rule :_list_stmt unless _tmp
|
1829
|
+
return _tmp
|
1830
|
+
end
|
1831
|
+
|
1832
|
+
Rules = {}
|
1833
|
+
Rules[:_upcase_letter] = rule_info("upcase_letter", "/[A-Z]/")
|
1834
|
+
Rules[:_downcase_letter] = rule_info("downcase_letter", "/[a-z]/")
|
1835
|
+
Rules[:_suffix_letter] = rule_info("suffix_letter", "/[=!?]/")
|
1836
|
+
Rules[:_letter] = rule_info("letter", "(upcase_letter | downcase_letter)")
|
1837
|
+
Rules[:_id_symbol] = rule_info("id_symbol", "(letter | \"_\" | [0-9])")
|
1838
|
+
Rules[:_vm_identifier] = rule_info("vm_identifier", "< (downcase_letter | \"_\") id_symbol* suffix_letter? > { SymbolEntry.new(:variable, text) }")
|
1839
|
+
Rules[:_variable_identifier] = rule_info("variable_identifier", "< (downcase_letter | \"_\") id_symbol* > { SymbolEntry.new(:variable, text) }")
|
1840
|
+
Rules[:_constant_identifier] = rule_info("constant_identifier", "< upcase_letter id_symbol* > { SymbolEntry.new(:constant, text) }")
|
1841
|
+
Rules[:_global_identifier] = rule_info("global_identifier", "< \"$\" (constant_identifier | variable_identifier) > { SymbolEntry.new(:global, text) }")
|
1842
|
+
Rules[:_local_internal_identifier] = rule_info("local_internal_identifier", "(constant_identifier | variable_identifier)")
|
1843
|
+
Rules[:_local_identifier] = rule_info("local_identifier", "(constant_identifier | vm_identifier)")
|
1844
|
+
Rules[:_instance_identifier] = rule_info("instance_identifier", "< \"@\" local_identifier > { SymbolEntry.new(:instance, text) }")
|
1845
|
+
Rules[:_classvar_identifier] = rule_info("classvar_identifier", "\"@@\" local_identifier:id { SymbolEntry.new(:classvar, id) }")
|
1846
|
+
Rules[:_identifier] = rule_info("identifier", "(global_identifier | instance_identifier | classvar_identifier | local_identifier)")
|
1847
|
+
Rules[:_id_separator] = rule_info("id_separator", "< (\"::\" | \".\") > { text }")
|
1848
|
+
Rules[:_internal_class_module_chain] = rule_info("internal_class_module_chain", "(< local_internal_identifier:parent id_separator:sep internal_class_module_chain:child > { SymbolEntry.new(parent.type, text, [parent, child, sep]) } | local_identifier)")
|
1849
|
+
Rules[:_class_module_chain] = rule_info("class_module_chain", "(< identifier:parent id_separator:sep internal_class_module_chain:child > { SymbolEntry.new(parent.type, text, [parent, child, sep]) } | identifier)")
|
1850
|
+
Rules[:_sp] = rule_info("sp", "/[ \\t]/")
|
1851
|
+
Rules[:__hyphen_] = rule_info("-", "sp+")
|
1852
|
+
Rules[:_dbl_escapes] = rule_info("dbl_escapes", "(\"\\\\\\\"\" { '\"' } | \"\\\\n\" { \"\\n\" } | \"\\\\t\" { \"\\t\" } | \"\\\\\\\\\" { \"\\\\\" })")
|
1853
|
+
Rules[:_escapes] = rule_info("escapes", "(\"\\\\\\\"\" { '\"' } | \"\\\\n\" { \"\\n\" } | \"\\\\t\" { \"\\t\" } | \"\\\\ \" { \" \" } | \"\\\\:\" { \":\" } | \"\\\\\\\\\" { \"\\\\\" })")
|
1854
|
+
Rules[:_dbl_seq] = rule_info("dbl_seq", "< /[^\\\\\"]+/ > { text }")
|
1855
|
+
Rules[:_dbl_not_quote] = rule_info("dbl_not_quote", "(dbl_escapes | dbl_seq)+:ary { ary }")
|
1856
|
+
Rules[:_dbl_string] = rule_info("dbl_string", "\"\\\"\" dbl_not_quote:ary \"\\\"\" { ary.join }")
|
1857
|
+
Rules[:_not_space_colon] = rule_info("not_space_colon", "(escapes | < /[^ \\t\\n:]/ > { text })")
|
1858
|
+
Rules[:_not_space_colons] = rule_info("not_space_colons", "not_space_colon+:ary { ary.join }")
|
1859
|
+
Rules[:_filename] = rule_info("filename", "(dbl_string | not_space_colons)")
|
1860
|
+
Rules[:_file_pos_sep] = rule_info("file_pos_sep", "(sp+ | \":\")")
|
1861
|
+
Rules[:_integer] = rule_info("integer", "< /[0-9]+/ > { text.to_i }")
|
1862
|
+
Rules[:_line_number] = rule_info("line_number", "integer")
|
1863
|
+
Rules[:_vm_offset] = rule_info("vm_offset", "\"@\" integer:int { Position.new(nil, nil, :offset, int) }")
|
1864
|
+
Rules[:_position] = rule_info("position", "(vm_offset | line_number:l { Position.new(nil, nil, :line, l) })")
|
1865
|
+
Rules[:_location] = rule_info("location", "(position | < filename >:file &{ File.exist?(file) } file_pos_sep position:pos { Position.new(:file, file, pos.position_type, pos.position) } | < filename >:file &{ File.exist?(file) } { Position.new(:file, file, nil, nil) } | class_module_chain?:fn file_pos_sep position:pos { Position.new(:fn, fn, pos.position_type, pos.position) } | class_module_chain?:fn { Position.new(:fn, fn, nil, nil) })")
|
1866
|
+
Rules[:_if_unless] = rule_info("if_unless", "< (\"if\" | \"unless\") > { text }")
|
1867
|
+
Rules[:_condition] = rule_info("condition", "< /.+/ > { text}")
|
1868
|
+
Rules[:_breakpoint_stmt_no_condition] = rule_info("breakpoint_stmt_no_condition", "location:loc { Breakpoint.new(loc, false, 'true') }")
|
1869
|
+
Rules[:_breakpoint_stmt] = rule_info("breakpoint_stmt", "(location:loc - if_unless:iu - condition:cond { Breakpoint.new(loc, iu == 'unless', cond) } | breakpoint_stmt_no_condition)")
|
1870
|
+
Rules[:_list_special_targets] = rule_info("list_special_targets", "< \".\" \"-\" > { text }")
|
1871
|
+
Rules[:_list_stmt] = rule_info("list_stmt", "(list_special_target | location):loc - integer:int? { List.new(loc, int) }")
|
1872
|
+
end
|
1873
|
+
if __FILE__ == $0
|
1874
|
+
# require 'rubygems'; require_relative '../lib/trepanning';
|
1875
|
+
|
1876
|
+
cp = CmdParse.new('', true)
|
1877
|
+
%w(A::B @@classvar abc01! @ivar @ivar.meth
|
1878
|
+
Object A::B::C A::B::C::D A::B.c A.b.c.d).each do |name|
|
1879
|
+
cp.setup_parser(name, true)
|
1880
|
+
# debugger if name == '@ivar.meth'
|
1881
|
+
res = cp._class_module_chain
|
1882
|
+
p res
|
1883
|
+
p cp.string
|
1884
|
+
p cp.result
|
1885
|
+
end
|
1886
|
+
%w(A::B:5 A::B:@5 @@classvar abc01!:10 @ivar).each do |name|
|
1887
|
+
cp.setup_parser(name, true)
|
1888
|
+
res = cp._location
|
1889
|
+
p res
|
1890
|
+
p cp.string
|
1891
|
+
p cp.result
|
1892
|
+
end
|
1893
|
+
# require 'trepanning';
|
1894
|
+
["#{__FILE__}:10", 'A::B 5',
|
1895
|
+
"#{__FILE__} 20"].each do |name|
|
1896
|
+
cp.setup_parser(name, true)
|
1897
|
+
res = cp._location
|
1898
|
+
p res
|
1899
|
+
p cp.string
|
1900
|
+
p cp.result
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
['filename', '"this is a filename"',
|
1904
|
+
'this\ is\ another\ filename',
|
1905
|
+
'C\:filename'
|
1906
|
+
].each do |name|
|
1907
|
+
puts '-' * 10
|
1908
|
+
cp.setup_parser(name, true)
|
1909
|
+
res = cp._filename
|
1910
|
+
p res
|
1911
|
+
puts cp.string
|
1912
|
+
puts cp.result
|
1913
|
+
end
|
1914
|
+
end
|