metal 0.0.2 → 0.0.3

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.
@@ -1,386 +1 @@
1
- #
2
- # Metal Runtime
3
- #
4
- # Copyright (C) 2008 FURUHASHI Sadayuki
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- module Metal
20
- class ParserBase
21
- def initialize(root = :main)
22
- @root = root
23
- end
24
-
25
- def parse(source, *args)
26
- parser = self.dup
27
- parser.initialize_parser(source, *args)
28
- parser.apply(@root)
29
- end
30
-
31
- def initialize_parser(source, *args)
32
- @input = case source
33
- when IO
34
- source.read.scan(/./m)
35
- when String
36
- source.scan(/./m)
37
- when Array
38
- source
39
- else
40
- source
41
- end
42
- @cache = Hash.new {|hash, key| hash[key] = {} }
43
- @index = 0
44
- @error_history = []
45
- @call_stack = []
46
- @label_stack = []
47
- @current_rule = nil
48
- input = @input
49
- error_history = @error_history
50
- @error_class = Class.new(ParseError) {
51
- const_set(:INPUT, input)
52
- const_set(:ERROR_HISTORY, error_history)
53
- }
54
- end
55
-
56
- class ParseError < RuntimeError
57
- def initialize(msg, index, call_stack)
58
- super(msg)
59
- @index = index
60
- @call_stack = call_stack
61
- end
62
- attr_reader :index
63
- def to_s
64
- super.gsub("\n", "\n ")
65
- end
66
- def message(rec = false)
67
- if rec
68
- input = self.class::INPUT
69
- parsed = input[0, @index].to_s.split("\n")
70
- line = parsed.length
71
- column = (line == 0 ? 0 : parsed.last.length)
72
- help = input[@index, 10]
73
- help = help.join if help.is_a?(Array)
74
- help << '...' if help.length == 10
75
- help.gsub!("\r", '\r')
76
- help.gsub!("\n", '\n')
77
- help.gsub!("\t", '\t')
78
- help = "'#{help}'"
79
- msg = " #{@call_stack.join('> ')}\n at line #{line}, column #{column} #{help.ljust(18)} #{super()}"
80
- else
81
- msg = "parse error:\n"
82
- s = 0
83
- self.class::ERROR_HISTORY.dup.push(self).sort_by{|e| [-e.index, s+=1] }.each_with_index {|(err,s), i|
84
- #self.class::ERROR_HISTORY.dup.push(self).reverse.each_with_index {|err, i|
85
- msg << "\n" << err.message(true)
86
- if i > 5
87
- msg << "\n ...\n"
88
- break
89
- end
90
- }
91
- end
92
- msg
93
- end
94
- end
95
-
96
- class LeftRecursion
97
- def initialize
98
- @call_stack = nil
99
- end
100
- attr_accessor :call_stack
101
- end
102
-
103
- class Memo
104
- def initialize(ret, pos)
105
- @ret = ret
106
- @pos = pos
107
- end
108
- attr_accessor :ret, :pos
109
- end
110
-
111
- def apply(rule, *args)
112
- @current_rule = rule
113
- @call_stack.push rule
114
-
115
- #p @label_stack.map {|l| l.join(':') }.join(',')
116
- #cache_name = "#{rule}@#{@label_stack.map{|l|l.join(':')}.join(',')}"
117
- cache_name = "#{rule}" # FIXME left recursion
118
- # cache_name = "#{rule}@#{@label_stack.inspect}"
119
-
120
- method_name = "rule_#{rule}"
121
-
122
- unless args.empty?
123
- return __send__(method_name, *args)
124
- end
125
-
126
- #labeled = nil
127
- #if @label_stack.last
128
- # labeled = true
129
- #end
130
- # if @label_stack.last && !@label_stack.last.shift
131
- # @label_stack.pop
132
- # #labeled = false
133
- # end
134
-
135
- #puts "#{rule}@#{@label_stack.inspect}: cache: #{@cache["#{rule}@#{@label_stack.inspect}"].inspect}"
136
-
137
- if memo = @cache[cache_name][@index]
138
- if memo.ret.class == LeftRecursion
139
- memo.ret.call_stack = @call_stack[0..-1]
140
- parse_error "left recursion"
141
- end
142
- #puts "#{cache_name}: cached #{@index} to #{memo.pos} (#{memo.ret.inspect})"
143
- @index = memo.pos
144
- return memo.ret
145
- else
146
- #begin XXX
147
- start_pos = @index
148
- lr = LeftRecursion.new
149
- memo = @cache[cache_name][start_pos] = Memo.new(lr, start_pos)
150
- memo.ret = __send__(method_name)
151
- memo.pos = @index
152
- #puts "#{cache_name}: uncached #{start_pos} to #{@index} (#{memo.ret.inspect})"
153
- #if labeled != nil
154
- # cache_name = "#{rule}@#{@label_stack.inspect}"
155
- # puts "ncn: #{cache_name} #{start_pos} -> #{memo.inspect}"
156
- # memo = @cache[cache_name][start_pos] = Memo.new(memo.ret, memo.pos)
157
- #end
158
- if lr.call_stack
159
- $stderr.puts "#{@call_stack.inspect}: left recursion" # FIXME left recursion
160
- parse_error "left recursion" # FIXME left recursion
161
- # #puts "#{cache_name}: lr start"
162
- # finish_pos = @index
163
- # #puts "#{cache_name}: detected on #{@index} from #{memo.pos}"
164
- # #puts "#{cache_name}: rewind stack: #{lr.call_stack[@call_stack.length..-1].inspect}"
165
- # @label_stack.push(lr.call_stack[@call_stack.length..-1])
166
- # while true
167
- # @index = start_pos
168
- # memo.ret = __send__(method_name)
169
- # #puts "#{cache_name}: recalled, moved to #{@index}"
170
- # memo.pos = @index
171
- # break if finish_pos <= @index
172
- # #if finish_pos <= @index
173
- # # p "lr growed #{cache_name} #{start_pos} to #{@index} #{memo.ret.inspect}"
174
- # # #p memo
175
- # # #p @cache[cache_name][start_pos]
176
- # # #nmemo = @cache[cache_name][start_pos]
177
- # # #if nmemo && memo.pos <= nmemo.pos
178
- # # # @index = nmemo.pos
179
- # # # memo = nmemo
180
- # # #end
181
- # # #break
182
- # # nmemo = @cache[cache_name][start_pos]
183
- # # if nmemo && memo.pos <= nmemo.pos
184
- # # memo = nmemo
185
- # # @index = memo.pos
186
- # # end
187
- # # #begin
188
- # # # @index = start_pos
189
- # # # p "JKJK"
190
- # # # ret = __send__(method_name)
191
- # # # if memo.pos <= @index
192
- # # # memo.ret = ret
193
- # # # memo.pos = @index
194
- # # # end
195
- # # #rescue
196
- # # # break
197
- # # # p $!
198
- # # #end
199
- # # break
200
- # #end
201
- # end
202
- # #puts "#{cache_name}: lr end #{start_pos} -> #{@index}"
203
- end
204
- memo.ret
205
- #rescue ParseError # XXX
206
- # @cache[cache_name][@index] = nil
207
- # raise
208
- #end
209
- end
210
-
211
- #rescue
212
- # if $!.to_s == '"k" is expected'
213
- # require 'pp'
214
- # pp caller
215
- # end
216
- # raise
217
- ensure
218
- @call_stack.pop
219
- end
220
-
221
- def act_or_message(err)
222
- msg = "One of following expressions expected:"
223
- err.each {|e| msg << "\n " << e.to_s }
224
- msg
225
- end
226
- private :act_or_message
227
-
228
- def act_or(blocks)
229
- err = []
230
- pos = @index
231
- blocks.each {|block|
232
- begin
233
- ret = block.call
234
- @error_history.concat err
235
- return ret
236
- rescue ParseError
237
- @index = pos
238
- err.push $!
239
- end
240
- }
241
- parse_error act_or_message(err)
242
- end
243
-
244
- def act_many(block)
245
- ret = []
246
- while true
247
- pos = @index
248
- begin
249
- ret.push block.call
250
- return ret if pos == @index # XXX many in many avoidance
251
- rescue ParseError
252
- @index = pos
253
- @error_history.push $!
254
- return ret
255
- end
256
- end
257
- end
258
-
259
- def act_many1(block)
260
- ret = []
261
- while true
262
- pos = @index
263
- begin
264
- ret.push block.call
265
- return ret if pos == @index # XXX many in many avoidance
266
- rescue ParseError
267
- @index = pos
268
- raise if ret.empty?
269
- @error_history.push $!
270
- return ret
271
- end
272
- end
273
- end
274
-
275
- def act_may(block)
276
- pos = @index
277
- begin
278
- block.call
279
- rescue ParseError
280
- @index = pos
281
- @error_history.push $!
282
- nil
283
- end
284
- end
285
-
286
-
287
- def act_not(block)
288
- pos = @index
289
- unless begin
290
- block.call
291
- nil
292
- rescue ParseError
293
- true
294
- ensure
295
- @index = pos
296
- end
297
- parse_error "not prediction failed"
298
- end
299
- end
300
-
301
- def act_lookahead(block)
302
- pos = @index
303
- begin
304
- block.call
305
- ensure
306
- @index = pos
307
- end
308
- end
309
-
310
- def act_where(block)
311
- unless block.call
312
- parse_error "where prediction failed"
313
- end
314
- end
315
-
316
- def act_any
317
- next_char
318
- end
319
-
320
- def act_char(c)
321
- pos = @index
322
- n = next_char
323
- unless c == n
324
- @index = pos
325
- parse_error "#{c.inspect} is expected"
326
- end
327
- n
328
- end
329
-
330
- def act_charset(set)
331
- pos = @index
332
- n = next_char
333
- if n.count(set) == 0
334
- @index = pos
335
- parse_error "character set [#{set.inspect[1..-2]}] is expected"
336
- end
337
- n
338
- end
339
-
340
- def act_token(str)
341
- pos = @index
342
- begin
343
- str.scan(/./m) {|c|
344
- act_char(c)
345
- }
346
- str
347
- rescue ParseError
348
- @index = pos
349
- parse_error "#{str.inspect} is expected"
350
- end
351
- end
352
-
353
- def rule_end
354
- if begin
355
- c = next_char
356
- @index -= 1
357
- true
358
- rescue
359
- nil
360
- end
361
- parse_error "unexpected character '#{c}', EOF expected"
362
- end
363
- end
364
-
365
- protected
366
- def error(msg)
367
- parse_error(msg)
368
- end
369
-
370
- private
371
- def next_char
372
- unless c = @input[@index]
373
- parse_error "Unexpected end of input"
374
- end
375
- @index += 1
376
- c
377
- end
378
-
379
- def parse_error(msg)
380
- raise @error_class.new(msg, @index, @call_stack.dup)
381
- end
382
-
383
- end
384
- end
385
-
386
-
1
+ require 'metal_runtime'
@@ -2,7 +2,7 @@ module Metal
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 2
5
+ TINY = 3
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - FURUHASHI Sadayuki
@@ -9,18 +9,28 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-24 00:00:00 +09:00
12
+ date: 2008-08-06 00:00:00 +09:00
13
13
  default_executable:
14
- dependencies: []
15
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.7.0
24
+ version:
16
25
  description: An object-oriented parser generator based on Parser Expression Grammar
17
26
  email:
18
27
  - fr _at_ syuki.skr.jp
19
28
  executables:
20
29
  - metal
21
30
  - metal-run
22
- extensions: []
23
-
31
+ extensions:
32
+ - ext/metal/runtime/extconf.rb
33
+ - ext/metal/boot/metal_boot_extconf.rb
24
34
  extra_rdoc_files:
25
35
  - License.txt
26
36
  - Manifest.txt
@@ -34,8 +44,21 @@ files:
34
44
  - bin/metal-run
35
45
  - config/hoe.rb
36
46
  - config/requirements.rb
47
+ - ext/metal/boot/metal_boot.h
48
+ - ext/metal/boot/metal_boot.metal
49
+ - ext/metal/boot/metal_boot.mm
50
+ - ext/metal/boot/metal_boot_extconf.rb
51
+ - ext/metal/boot/metal_boot_rb.mm
52
+ - ext/metal/runtime/extconf.rb
53
+ - ext/metal/runtime/input.mm
54
+ - ext/metal/runtime/rbinit.mm
55
+ - ext/metal/runtime/runtime.mm
56
+ - include/metal.h
57
+ - include/metal/exception.h
58
+ - include/metal/input.h
59
+ - include/metal/rbcode.h
60
+ - include/metal/runtime.h
37
61
  - lib/metal.rb
38
- - lib/metal/boot.metal
39
62
  - lib/metal/boot.rb
40
63
  - lib/metal/generator.rb
41
64
  - lib/metal/runtime.rb
@@ -56,6 +79,7 @@ rdoc_options:
56
79
  - README.txt
57
80
  require_paths:
58
81
  - lib
82
+ - ext
59
83
  required_ruby_version: !ruby/object:Gem::Requirement
60
84
  requirements:
61
85
  - - ">="
@@ -71,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
95
  requirements: []
72
96
 
73
97
  rubyforge_project: metal
74
- rubygems_version: 1.1.1
98
+ rubygems_version: 1.2.0
75
99
  signing_key:
76
100
  specification_version: 2
77
101
  summary: An object-oriented parser generator based on Parser Expression Grammar