onion 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/{README.rdoc → License.txt} +2 -19
- data/README.txt +34 -0
- data/lib/onion.rb +2 -2
- data/lib/onion/control_client.rb +87 -0
- data/lib/onion/elements.rb +4 -0
- data/lib/onion/elements/circuit.rb +11 -0
- data/lib/onion/elements/circuit_list.rb +18 -0
- data/lib/onion/elements/router.rb +3 -3
- data/lib/onion/elements/router_list.rb +4 -6
- data/lib/onion/elements/stream.rb +12 -0
- data/lib/onion/elements/stream_list.rb +20 -0
- data/lib/onion/parsers/circuit_lists.rb +491 -0
- data/lib/onion/parsers/circuit_lists.treetop +53 -0
- data/lib/onion/parsers/common.rb +1692 -0
- data/lib/onion/parsers/common.treetop +127 -0
- data/lib/onion/parsers/router_statuses.rb +1035 -0
- data/lib/onion/parsers/router_statuses.treetop +111 -0
- data/lib/onion/parsers/stream_lists.rb +356 -0
- data/lib/onion/parsers/stream_lists.treetop +32 -0
- data/lib/tasks/treetop.rake +1 -1
- metadata +18 -5
- data/lib/onion/parsers/router_lists.treetop +0 -133
data/{README.rdoc → License.txt}
RENAMED
@@ -1,22 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
== Introduction
|
4
|
-
|
5
|
-
Onion is a library for interacting with Tor. Onion is in an alpha state and is
|
6
|
-
made availible for early adopters and contributors only.
|
7
|
-
|
8
|
-
== Functionality
|
9
|
-
|
10
|
-
* Parse router status entries per the directory protocol version 2.0.
|
11
|
-
|
12
|
-
== Authors
|
13
|
-
|
14
|
-
Onion was written by Tim Sally <poet@stack.io>. Please send bug reports and
|
15
|
-
suggestions to the author.
|
16
|
-
|
17
|
-
== License
|
18
|
-
|
19
|
-
(The MIT License)
|
1
|
+
LICENSE.txt
|
2
|
+
===========
|
20
3
|
|
21
4
|
Copyright (c) 2010 Tim Sally
|
22
5
|
|
data/README.txt
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
README.txt
|
2
|
+
==========
|
3
|
+
|
4
|
+
Introduction
|
5
|
+
------------
|
6
|
+
|
7
|
+
Onion is a library for interacting with Tor. Onion is in an alpha state and is
|
8
|
+
made available for early adopters and contributors only.
|
9
|
+
|
10
|
+
Basic Concepts
|
11
|
+
--------------
|
12
|
+
|
13
|
+
Elements are pieces of the Tor network. Routers, circuits, and streams are
|
14
|
+
examples of elements. You don't care about how the library gets these, you
|
15
|
+
just want to be able to interact with them. Methods in the Control Client
|
16
|
+
return elements.
|
17
|
+
|
18
|
+
Parsers take information received from Tor and turn the information into
|
19
|
+
elements. Parsers are used internally by the Control Client to create elements
|
20
|
+
to return to the user.
|
21
|
+
|
22
|
+
The Control Client is what you can use in scripts to interact with Tor.
|
23
|
+
|
24
|
+
Authors
|
25
|
+
-------
|
26
|
+
|
27
|
+
Onion was written by Tim Sally <poet@stack.io>. Please send bug reports and
|
28
|
+
suggestions to the author.
|
29
|
+
|
30
|
+
License
|
31
|
+
-------
|
32
|
+
|
33
|
+
Copyright (c) 2010 Tim Sally and provided under the MIT License. Please see
|
34
|
+
LICENSE.txt for details.
|
data/lib/onion.rb
CHANGED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
module Onion
|
5
|
+
# Onion::ControlClient is a client to the Tor Control Protocol.
|
6
|
+
class ControlClient
|
7
|
+
attr_reader :host, :port
|
8
|
+
|
9
|
+
def initialize(host="127.0.0.1", port=9051, log_level=Logger::ERROR)
|
10
|
+
@log = Logger.new(STDOUT)
|
11
|
+
@log.level = log_level
|
12
|
+
|
13
|
+
@host = host # Host of the Tor process.
|
14
|
+
@port = port # Port accepting the Tor Control Protocol.
|
15
|
+
@sock = TCPSocket.new(host, port)
|
16
|
+
|
17
|
+
@log.info("[TOR CONTROL CLIENT ] Connected to #{host}:#{port}.")
|
18
|
+
end
|
19
|
+
|
20
|
+
def send(text)
|
21
|
+
@sock << "#{text}\r\n"
|
22
|
+
@log.debug("[TOR CONTROL CLIENT] #{text}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def authenticate(pass="\"\"")
|
26
|
+
send("authenticate #{pass}")
|
27
|
+
@log.debug("[TOR CONTROL CLIENT] #{@sock.gets}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def extend_circuit(specs, id=0)
|
31
|
+
send("extendcircuit #{id} #{specs.join(",")}")
|
32
|
+
response = @sock.gets
|
33
|
+
if response.split[1] == "EXTENDED"
|
34
|
+
@log.debug("[TOR CONTROL CLIENT] #{response}")
|
35
|
+
return response.split[2]
|
36
|
+
else
|
37
|
+
@log.warn("[TOR CONTROL CLIENT] Circuit (#{specs.join(",")}) was not extended.")
|
38
|
+
@log.warn("[TOR CONTROL CLIENT] #{response}.")
|
39
|
+
|
40
|
+
return -1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def attach_stream(stream_id, circuit_id)
|
45
|
+
send("attachstream #{stream_id} #{circuit_id}")
|
46
|
+
response = @sock.gets
|
47
|
+
if response.split[1] == "OK"
|
48
|
+
@log.info("[TOR CONTROL CLIENT] #{response}")
|
49
|
+
else
|
50
|
+
@log.warn("[TOR CONTROL CLIENT] Stream #{stream_id} was not attached to circuit #{circuit_id}.")
|
51
|
+
@log.warn("[TOR CONTROL CLIENT] #{response}.")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def router_status_info(nicknames=nil,fingerprints=nil)
|
56
|
+
statuses = ""
|
57
|
+
|
58
|
+
p "start!"
|
59
|
+
|
60
|
+
if nicknames
|
61
|
+
nicknames.each do |name|
|
62
|
+
send("getinfo ns/name/#{name}")
|
63
|
+
statuses << @sock.gets
|
64
|
+
end
|
65
|
+
while not @sock.eof?
|
66
|
+
statuses << @sock.gets
|
67
|
+
end
|
68
|
+
end
|
69
|
+
p "done!"
|
70
|
+
Onion::RouterList.new(statuses)
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_stream_status
|
74
|
+
send("getinfo stream-status")
|
75
|
+
result = []
|
76
|
+
line = @sock.gets
|
77
|
+
while line != "250 OK\r\n"
|
78
|
+
unless line == "250+stream-status=\r\n" or line == ".\r\n"
|
79
|
+
line = line.gsub("250-stream-status=", "")
|
80
|
+
result << line
|
81
|
+
end
|
82
|
+
line = @sock.gets
|
83
|
+
end
|
84
|
+
return result
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/onion/elements.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
module Onion
|
2
|
+
autoload :Circuit, 'onion/elements/circuit'
|
3
|
+
autoload :CircuitList, 'onion/elements/circuit_list'
|
2
4
|
autoload :Router, 'onion/elements/router'
|
3
5
|
autoload :RouterList, 'onion/elements/router_list'
|
6
|
+
autoload :Stream, 'onion/elements/stream'
|
7
|
+
autoload :StreamList, 'onion/elements/stream_list'
|
4
8
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Onion
|
2
|
+
# Onion::CircuitList is a list of Onion::Circuit objects.
|
3
|
+
class CircuitList
|
4
|
+
attr_reader :circuits
|
5
|
+
def initialize(text)
|
6
|
+
if text.blank?
|
7
|
+
@circuits = []
|
8
|
+
return self
|
9
|
+
end
|
10
|
+
parser = Onion::CircuitListsParser.new
|
11
|
+
if nodes = parser.parse(text)
|
12
|
+
@circuits = nodes.circuits
|
13
|
+
else
|
14
|
+
raise Exception, "Couldn't parse #{text} b/c #{parser.failure_reason}."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Onion
|
2
2
|
# Onion::Router is a Ruby object representing a Tor router.
|
3
3
|
class Router
|
4
|
-
attr_reader :nick, :
|
5
|
-
def initialize(nick,
|
4
|
+
attr_reader :nick, :fingerprint, :status_flags
|
5
|
+
def initialize(nick, fingerprint, status_flags)
|
6
6
|
@nick = nick # Nickname of the router.
|
7
|
-
@
|
7
|
+
@fingerprint = fingerprint # Fingerprint of the router.
|
8
8
|
@status_flags = status_flags # Array of strings with status flags.
|
9
9
|
end
|
10
10
|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Onion
|
2
|
-
# Onion::RouterList is a list of Onion::Router objects.
|
3
|
-
# the text given is parsed with Onion::RouterListParser. The text should be
|
4
|
-
# in the router status format specified by the directory protocol 2.0 spec.
|
2
|
+
# Onion::RouterList is a list of Onion::Router objects.
|
5
3
|
class RouterList
|
6
4
|
attr_reader :routers
|
7
5
|
def initialize(text)
|
@@ -9,11 +7,11 @@ module Onion
|
|
9
7
|
@routers = []
|
10
8
|
return self
|
11
9
|
end
|
12
|
-
parser = Onion::
|
10
|
+
parser = Onion::RouterStatusesParser.new
|
13
11
|
if nodes = parser.parse(text)
|
14
12
|
@routers = nodes.routers
|
15
13
|
else
|
16
|
-
raise Exception "Couldn't parse #{text} b/c #{parser.failure_reason}."
|
14
|
+
raise Exception, "Couldn't parse #{text} b/c #{parser.failure_reason}."
|
17
15
|
end
|
18
16
|
end
|
19
17
|
|
@@ -29,7 +27,7 @@ module Onion
|
|
29
27
|
|
30
28
|
# Returns the routers that are neither guard or exit routers.
|
31
29
|
def middlemen
|
32
|
-
@routers.
|
30
|
+
@routers.reject { |r| r.guard? or r.exit? }
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Onion
|
2
|
+
# Onion::StreamList is a list of Onion::Stream objects.
|
3
|
+
class StreamList
|
4
|
+
attr_reader :streams
|
5
|
+
def initialize(text)
|
6
|
+
if text.blank?
|
7
|
+
@streams = []
|
8
|
+
return self
|
9
|
+
end
|
10
|
+
|
11
|
+
parser = Onion::StreamListsParser.new
|
12
|
+
if nodes = parser.parse(text)
|
13
|
+
@streams = nodes.streams
|
14
|
+
else
|
15
|
+
raise Exception, "Couldn't parse #{text} b/c #{parser.failure_reason}."
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,491 @@
|
|
1
|
+
# Autogenerated from a Treetop grammar. Edits may be lost.
|
2
|
+
|
3
|
+
|
4
|
+
module Onion
|
5
|
+
module CircuitLists
|
6
|
+
include Treetop::Runtime
|
7
|
+
|
8
|
+
def root
|
9
|
+
@root ||= :circuit_list
|
10
|
+
end
|
11
|
+
|
12
|
+
include Common
|
13
|
+
|
14
|
+
module CircuitList0
|
15
|
+
def circuits
|
16
|
+
circuits = []
|
17
|
+
self.elements.each do |circuit|
|
18
|
+
if circuit.respond_to? :p
|
19
|
+
to_process = [circuit.p.first]
|
20
|
+
counter = 1
|
21
|
+
circuit.p.rest.elements.each do |e|
|
22
|
+
to_process << e.LongName
|
23
|
+
end
|
24
|
+
routers = []
|
25
|
+
to_process.each do |router|
|
26
|
+
if router.respond_to? :n
|
27
|
+
routers << Router.new(router.n.text_value.strip, router.f.text_value.strip, nil)
|
28
|
+
else
|
29
|
+
routers << Router.new(nil, nil, nil)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
circuits << Circuit.new(circuit.id.text_value.strip, routers)
|
33
|
+
else
|
34
|
+
circuits << Circuit.new(circuit.id.text_value.strip, [])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
return circuits
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def _nt_circuit_list
|
42
|
+
start_index = index
|
43
|
+
if node_cache[:circuit_list].has_key?(index)
|
44
|
+
cached = node_cache[:circuit_list][index]
|
45
|
+
if cached
|
46
|
+
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
47
|
+
@index = cached.interval.end
|
48
|
+
end
|
49
|
+
return cached
|
50
|
+
end
|
51
|
+
|
52
|
+
s0, i0 = [], index
|
53
|
+
loop do
|
54
|
+
r1 = _nt_circuit_list_entry
|
55
|
+
if r1
|
56
|
+
s0 << r1
|
57
|
+
else
|
58
|
+
break
|
59
|
+
end
|
60
|
+
end
|
61
|
+
if s0.empty?
|
62
|
+
@index = i0
|
63
|
+
r0 = nil
|
64
|
+
else
|
65
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
66
|
+
r0.extend(CircuitList0)
|
67
|
+
end
|
68
|
+
|
69
|
+
node_cache[:circuit_list][start_index] = r0
|
70
|
+
|
71
|
+
r0
|
72
|
+
end
|
73
|
+
|
74
|
+
module CircuitListEntry0
|
75
|
+
def id
|
76
|
+
elements[0]
|
77
|
+
end
|
78
|
+
|
79
|
+
def SP1
|
80
|
+
elements[1]
|
81
|
+
end
|
82
|
+
|
83
|
+
def s
|
84
|
+
elements[2]
|
85
|
+
end
|
86
|
+
|
87
|
+
def SP2
|
88
|
+
elements[3]
|
89
|
+
end
|
90
|
+
|
91
|
+
def p
|
92
|
+
elements[4]
|
93
|
+
end
|
94
|
+
|
95
|
+
def SP3
|
96
|
+
elements[5]
|
97
|
+
end
|
98
|
+
|
99
|
+
def purp
|
100
|
+
elements[7]
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
module CircuitListEntry1
|
106
|
+
def id
|
107
|
+
elements[0]
|
108
|
+
end
|
109
|
+
|
110
|
+
def SP1
|
111
|
+
elements[1]
|
112
|
+
end
|
113
|
+
|
114
|
+
def s
|
115
|
+
elements[2]
|
116
|
+
end
|
117
|
+
|
118
|
+
def SP2
|
119
|
+
elements[3]
|
120
|
+
end
|
121
|
+
|
122
|
+
def p
|
123
|
+
elements[4]
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
module CircuitListEntry2
|
129
|
+
def id
|
130
|
+
elements[0]
|
131
|
+
end
|
132
|
+
|
133
|
+
def SP
|
134
|
+
elements[1]
|
135
|
+
end
|
136
|
+
|
137
|
+
def s
|
138
|
+
elements[2]
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
def _nt_circuit_list_entry
|
144
|
+
start_index = index
|
145
|
+
if node_cache[:circuit_list_entry].has_key?(index)
|
146
|
+
cached = node_cache[:circuit_list_entry][index]
|
147
|
+
if cached
|
148
|
+
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
149
|
+
@index = cached.interval.end
|
150
|
+
end
|
151
|
+
return cached
|
152
|
+
end
|
153
|
+
|
154
|
+
i0 = index
|
155
|
+
i1, s1 = index, []
|
156
|
+
r2 = _nt_CircuitID
|
157
|
+
s1 << r2
|
158
|
+
if r2
|
159
|
+
r3 = _nt_SP
|
160
|
+
s1 << r3
|
161
|
+
if r3
|
162
|
+
r4 = _nt_CircStatus
|
163
|
+
s1 << r4
|
164
|
+
if r4
|
165
|
+
r5 = _nt_SP
|
166
|
+
s1 << r5
|
167
|
+
if r5
|
168
|
+
r6 = _nt_Path
|
169
|
+
s1 << r6
|
170
|
+
if r6
|
171
|
+
r7 = _nt_SP
|
172
|
+
s1 << r7
|
173
|
+
if r7
|
174
|
+
if has_terminal?("PURPOSE=", false, index)
|
175
|
+
r8 = instantiate_node(SyntaxNode,input, index...(index + 8))
|
176
|
+
@index += 8
|
177
|
+
else
|
178
|
+
terminal_parse_failure("PURPOSE=")
|
179
|
+
r8 = nil
|
180
|
+
end
|
181
|
+
s1 << r8
|
182
|
+
if r8
|
183
|
+
r9 = _nt_Purpose
|
184
|
+
s1 << r9
|
185
|
+
if r9
|
186
|
+
if has_terminal?("\n", false, index)
|
187
|
+
r10 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
188
|
+
@index += 1
|
189
|
+
else
|
190
|
+
terminal_parse_failure("\n")
|
191
|
+
r10 = nil
|
192
|
+
end
|
193
|
+
s1 << r10
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
if s1.last
|
203
|
+
r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
|
204
|
+
r1.extend(CircuitListEntry0)
|
205
|
+
else
|
206
|
+
@index = i1
|
207
|
+
r1 = nil
|
208
|
+
end
|
209
|
+
if r1
|
210
|
+
r0 = r1
|
211
|
+
else
|
212
|
+
i11, s11 = index, []
|
213
|
+
r12 = _nt_CircuitID
|
214
|
+
s11 << r12
|
215
|
+
if r12
|
216
|
+
r13 = _nt_SP
|
217
|
+
s11 << r13
|
218
|
+
if r13
|
219
|
+
r14 = _nt_CircStatus
|
220
|
+
s11 << r14
|
221
|
+
if r14
|
222
|
+
r15 = _nt_SP
|
223
|
+
s11 << r15
|
224
|
+
if r15
|
225
|
+
r16 = _nt_Path
|
226
|
+
s11 << r16
|
227
|
+
if r16
|
228
|
+
if has_terminal?("\n", false, index)
|
229
|
+
r17 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
230
|
+
@index += 1
|
231
|
+
else
|
232
|
+
terminal_parse_failure("\n")
|
233
|
+
r17 = nil
|
234
|
+
end
|
235
|
+
s11 << r17
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
if s11.last
|
242
|
+
r11 = instantiate_node(SyntaxNode,input, i11...index, s11)
|
243
|
+
r11.extend(CircuitListEntry1)
|
244
|
+
else
|
245
|
+
@index = i11
|
246
|
+
r11 = nil
|
247
|
+
end
|
248
|
+
if r11
|
249
|
+
r0 = r11
|
250
|
+
else
|
251
|
+
i18, s18 = index, []
|
252
|
+
r19 = _nt_CircuitID
|
253
|
+
s18 << r19
|
254
|
+
if r19
|
255
|
+
r20 = _nt_SP
|
256
|
+
s18 << r20
|
257
|
+
if r20
|
258
|
+
r21 = _nt_CircStatus
|
259
|
+
s18 << r21
|
260
|
+
if r21
|
261
|
+
if has_terminal?("\n", false, index)
|
262
|
+
r22 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
263
|
+
@index += 1
|
264
|
+
else
|
265
|
+
terminal_parse_failure("\n")
|
266
|
+
r22 = nil
|
267
|
+
end
|
268
|
+
s18 << r22
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
if s18.last
|
273
|
+
r18 = instantiate_node(SyntaxNode,input, i18...index, s18)
|
274
|
+
r18.extend(CircuitListEntry2)
|
275
|
+
else
|
276
|
+
@index = i18
|
277
|
+
r18 = nil
|
278
|
+
end
|
279
|
+
if r18
|
280
|
+
r0 = r18
|
281
|
+
else
|
282
|
+
@index = i0
|
283
|
+
r0 = nil
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
node_cache[:circuit_list_entry][start_index] = r0
|
289
|
+
|
290
|
+
r0
|
291
|
+
end
|
292
|
+
|
293
|
+
module Path0
|
294
|
+
def LongName
|
295
|
+
elements[1]
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
module Path1
|
300
|
+
def first
|
301
|
+
elements[0]
|
302
|
+
end
|
303
|
+
|
304
|
+
def rest
|
305
|
+
elements[1]
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def _nt_Path
|
310
|
+
start_index = index
|
311
|
+
if node_cache[:Path].has_key?(index)
|
312
|
+
cached = node_cache[:Path][index]
|
313
|
+
if cached
|
314
|
+
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
315
|
+
@index = cached.interval.end
|
316
|
+
end
|
317
|
+
return cached
|
318
|
+
end
|
319
|
+
|
320
|
+
i0, s0 = index, []
|
321
|
+
r1 = _nt_LongName
|
322
|
+
s0 << r1
|
323
|
+
if r1
|
324
|
+
s2, i2 = [], index
|
325
|
+
loop do
|
326
|
+
i3, s3 = index, []
|
327
|
+
if has_terminal?(",", false, index)
|
328
|
+
r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
329
|
+
@index += 1
|
330
|
+
else
|
331
|
+
terminal_parse_failure(",")
|
332
|
+
r4 = nil
|
333
|
+
end
|
334
|
+
s3 << r4
|
335
|
+
if r4
|
336
|
+
r5 = _nt_LongName
|
337
|
+
s3 << r5
|
338
|
+
end
|
339
|
+
if s3.last
|
340
|
+
r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
|
341
|
+
r3.extend(Path0)
|
342
|
+
else
|
343
|
+
@index = i3
|
344
|
+
r3 = nil
|
345
|
+
end
|
346
|
+
if r3
|
347
|
+
s2 << r3
|
348
|
+
else
|
349
|
+
break
|
350
|
+
end
|
351
|
+
end
|
352
|
+
r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
|
353
|
+
s0 << r2
|
354
|
+
end
|
355
|
+
if s0.last
|
356
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
357
|
+
r0.extend(Path1)
|
358
|
+
else
|
359
|
+
@index = i0
|
360
|
+
r0 = nil
|
361
|
+
end
|
362
|
+
|
363
|
+
node_cache[:Path][start_index] = r0
|
364
|
+
|
365
|
+
r0
|
366
|
+
end
|
367
|
+
|
368
|
+
def _nt_CircStatus
|
369
|
+
start_index = index
|
370
|
+
if node_cache[:CircStatus].has_key?(index)
|
371
|
+
cached = node_cache[:CircStatus][index]
|
372
|
+
if cached
|
373
|
+
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
374
|
+
@index = cached.interval.end
|
375
|
+
end
|
376
|
+
return cached
|
377
|
+
end
|
378
|
+
|
379
|
+
i0 = index
|
380
|
+
if has_terminal?("LAUNCHED", false, index)
|
381
|
+
r1 = instantiate_node(SyntaxNode,input, index...(index + 8))
|
382
|
+
@index += 8
|
383
|
+
else
|
384
|
+
terminal_parse_failure("LAUNCHED")
|
385
|
+
r1 = nil
|
386
|
+
end
|
387
|
+
if r1
|
388
|
+
r0 = r1
|
389
|
+
else
|
390
|
+
if has_terminal?("BUILT", false, index)
|
391
|
+
r2 = instantiate_node(SyntaxNode,input, index...(index + 5))
|
392
|
+
@index += 5
|
393
|
+
else
|
394
|
+
terminal_parse_failure("BUILT")
|
395
|
+
r2 = nil
|
396
|
+
end
|
397
|
+
if r2
|
398
|
+
r0 = r2
|
399
|
+
else
|
400
|
+
if has_terminal?("EXTENDED", false, index)
|
401
|
+
r3 = instantiate_node(SyntaxNode,input, index...(index + 8))
|
402
|
+
@index += 8
|
403
|
+
else
|
404
|
+
terminal_parse_failure("EXTENDED")
|
405
|
+
r3 = nil
|
406
|
+
end
|
407
|
+
if r3
|
408
|
+
r0 = r3
|
409
|
+
else
|
410
|
+
if has_terminal?("FAILED", false, index)
|
411
|
+
r4 = instantiate_node(SyntaxNode,input, index...(index + 6))
|
412
|
+
@index += 6
|
413
|
+
else
|
414
|
+
terminal_parse_failure("FAILED")
|
415
|
+
r4 = nil
|
416
|
+
end
|
417
|
+
if r4
|
418
|
+
r0 = r4
|
419
|
+
else
|
420
|
+
if has_terminal?("CLOSED", false, index)
|
421
|
+
r5 = instantiate_node(SyntaxNode,input, index...(index + 6))
|
422
|
+
@index += 6
|
423
|
+
else
|
424
|
+
terminal_parse_failure("CLOSED")
|
425
|
+
r5 = nil
|
426
|
+
end
|
427
|
+
if r5
|
428
|
+
r0 = r5
|
429
|
+
else
|
430
|
+
@index = i0
|
431
|
+
r0 = nil
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
node_cache[:CircStatus][start_index] = r0
|
439
|
+
|
440
|
+
r0
|
441
|
+
end
|
442
|
+
|
443
|
+
def _nt_Purpose
|
444
|
+
start_index = index
|
445
|
+
if node_cache[:Purpose].has_key?(index)
|
446
|
+
cached = node_cache[:Purpose][index]
|
447
|
+
if cached
|
448
|
+
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
449
|
+
@index = cached.interval.end
|
450
|
+
end
|
451
|
+
return cached
|
452
|
+
end
|
453
|
+
|
454
|
+
i0 = index
|
455
|
+
if has_terminal?("GENERAL", false, index)
|
456
|
+
r1 = instantiate_node(SyntaxNode,input, index...(index + 7))
|
457
|
+
@index += 7
|
458
|
+
else
|
459
|
+
terminal_parse_failure("GENERAL")
|
460
|
+
r1 = nil
|
461
|
+
end
|
462
|
+
if r1
|
463
|
+
r0 = r1
|
464
|
+
else
|
465
|
+
if has_terminal?("CONTROLER", false, index)
|
466
|
+
r2 = instantiate_node(SyntaxNode,input, index...(index + 9))
|
467
|
+
@index += 9
|
468
|
+
else
|
469
|
+
terminal_parse_failure("CONTROLER")
|
470
|
+
r2 = nil
|
471
|
+
end
|
472
|
+
if r2
|
473
|
+
r0 = r2
|
474
|
+
else
|
475
|
+
@index = i0
|
476
|
+
r0 = nil
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
node_cache[:Purpose][start_index] = r0
|
481
|
+
|
482
|
+
r0
|
483
|
+
end
|
484
|
+
|
485
|
+
end
|
486
|
+
|
487
|
+
class CircuitListsParser < Treetop::Runtime::CompiledParser
|
488
|
+
include CircuitLists
|
489
|
+
end
|
490
|
+
|
491
|
+
end
|