Parent

Racc::ParserFileGenerator

Constants

RUBY_PATH
RE_CACHE

Public Class Methods

new(states, params) click to toggle source
    # File lib/racc/parserfilegenerator.rb, line 72
72:     def initialize(states, params)
73:       @states = states
74:       @grammar = states.grammar
75:       @params = params
76:     end

Public Instance Methods

generate_parser() click to toggle source
    # File lib/racc/parserfilegenerator.rb, line 78
78:     def generate_parser
79:       string_io = StringIO.new
80: 
81:       init_line_conversion_system
82:       @f = string_io
83:       parser_file
84: 
85:       string_io.rewind
86:       string_io.read
87:     end
generate_parser_file(destpath) click to toggle source
    # File lib/racc/parserfilegenerator.rb, line 89
89:     def generate_parser_file(destpath)
90:       init_line_conversion_system
91:       File.open(destpath, 'w') {|f|
92:         @f = f
93:         parser_file
94:       }
95:       File.chmod 0755, destpath if @params.make_executable?
96:     end
put_state_transition_table(f) click to toggle source

State Transition Table Serialization

     # File lib/racc/parserfilegenerator.rb, line 254
254:     def put_state_transition_table(f)
255:       @f = f
256:       state_transition_table
257:     end

Private Instance Methods

actions() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 405
405:     def actions
406:       @grammar.each do |rule|
407:         unless rule.action.source?
408:           raise "racc: fatal: cannot generate parser file when any action is a Proc"
409:         end
410:       end
411: 
412:       if @params.result_var?
413:         decl = ', result'
414:         retval = "\n    result"
415:         default_body = ''
416:       else
417:         decl = ''
418:         retval = ''
419:         default_body = 'val[0]'
420:       end
421:       @grammar.each do |rule|
422:         line
423:         if rule.action.empty? and @params.omit_action_call?
424:           line "# reduce #{rule.ident} omitted"
425:         else
426:           src0 = rule.action.source || SourceText.new(default_body, __FILE__, 0)
427:           if @params.convert_line?
428:             src = remove_blank_lines(src0)
429:             delim = make_delimiter(src.text)
430:             @f.printf unindent_auto(              module_eval(<<'%s', '%s', %d)                def _reduce_%d(val, _values%s)                  %s%s                end              %s),
431:                       delim, src.filename, src.lineno - 1,
432:                         rule.ident, decl,
433:                         src.text, retval,
434:                       delim
435:           else
436:             src = remove_blank_lines(src0)
437:             @f.printf unindent_auto(              def _reduce_%d(val, _values%s)              %s%s              end),
438:                       rule.ident, decl,
439:                       src.text, retval
440:           end
441:         end
442:       end
443:       line
444:       @f.printf unindent_auto(        def _reduce_none(val, _values%s)          val[0]        end), decl
445:       line
446:     end
cref_pop() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 213
213:     def cref_pop
214:       @cref.pop
215:     end
cref_push(name) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 209
209:     def cref_push(name)
210:       @cref.push name
211:     end
detab(str, ts = 8) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 499
499:     def detab(str, ts = 8)
500:       add = 0
501:       len = nil
502:       str.gsub(/\t/) {
503:         len = ts - ($`.size + add) % ts
504:         add += len - 1
505:         ' ' * len
506:       }
507:     end
embed_library(src) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 136
136:     def embed_library(src)
137:       line %[###### #{src.filename} begin]
138:       line %[unless $".index '#{src.filename}']
139:       line %[$".push '#{src.filename}']
140:       put src, @params.convert_line?
141:       line %[end]
142:       line %[###### #{src.filename} end]
143:     end
header() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 167
167:     def header
168:       @params.header.each do |src|
169:         line
170:         put src, @params.convert_line_all?
171:       end
172:     end
i_i_sym_list(name, table) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 375
375:     def i_i_sym_list(name, table)
376:       sep = ''
377:       line "#{name} = ["
378:       table.each_slice(3) do |len, target, mid|
379:         @f.print sep; sep = ",\n"
380:         @f.printf '  %d, %d, %s', len, target, mid.inspect
381:       end
382:       line " ]"
383:     end
indent() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 217
217:     def indent
218:       @f.print '  ' * @cref.size
219:     end
indent_re(n) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 495
495:     def indent_re(n)
496:       RE_CACHE[n] ||= /\A {#{n}}/
497:     end
init_line_conversion_system() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 204
204:     def init_line_conversion_system
205:       @cref = []
206:       @used_separator = {}
207:     end
inner() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 174
174:     def inner
175:       @params.inner.each do |src|
176:         line
177:         put src, @params.convert_line?
178:       end
179:     end
integer_list(name, table) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 322
322:     def integer_list(name, table)
323:       if table.size > 2000
324:         serialize_integer_list_compressed name, table
325:       else
326:         serialize_integer_list_std name, table
327:       end
328:     end
line(str = '') click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 200
200:     def line(str = '')
201:       @f.puts str
202:     end
make_delimiter(body) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 471
471:     def make_delimiter(body)
472:       delim = '.,.,'
473:       while body.index(delim)
474:         delim *= 2
475:       end
476:       delim
477:     end
make_separator(src) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 233
233:     def make_separator(src)
234:       sep = unique_separator(src.filename)
235:       sep *= 2 while src.text.index(sep)
236:       sep
237:     end
minimum_indent(lines) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 485
485:     def minimum_indent(lines)
486:       lines.map {|line| n_indent(line) }.min
487:     end
n_indent(line) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 489
489:     def n_indent(line)
490:       line.slice(/\A\s+/).size
491:     end
notice() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 124
124:     def notice
125:       line %[#]
126:       line %[# DO NOT MODIFY!!!!]
127:       line %[# This file is automatically generated by Racc #{Racc::Version}]
128:       line %[# from Racc grammer file "#{@params.filename}".]
129:       line %[#]
130:     end
parser_class(classname, superclass) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 149
149:     def parser_class(classname, superclass)
150:       mods = classname.split('::')
151:       classid = mods.pop
152:       mods.each do |mod|
153:         indent; line "module #{mod}"
154:         cref_push mod
155:       end
156:       indent; line "class #{classid} < #{superclass}"
157:       cref_push classid
158:       yield
159:       cref_pop
160:       indent; line "end   \# class #{classid}"
161:       mods.reverse_each do |mod|
162:         indent; line "end   \# module #{mod}"
163:         cref_pop
164:       end
165:     end
parser_file() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 100
100:     def parser_file
101:       shebang @params.interpreter if @params.make_executable?
102:       notice
103:       line
104:       if @params.embed_runtime?
105:         embed_library runtime_source()
106:       else
107:         require 'racc/parser.rb'
108:       end
109:       header
110:       parser_class(@params.classname, @params.superclass) {
111:         inner
112:         state_transition_table
113:       }
114:       footer
115:     end
put(src, convert_line = false) click to toggle source

Low Level Routines

     # File lib/racc/parserfilegenerator.rb, line 190
190:     def put(src, convert_line = false)
191:       if convert_line
192:         replace_location(src) {
193:           @f.puts src.text
194:         }
195:       else
196:         @f.puts src.text
197:       end
198:     end
remove_blank_lines(src) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 462
462:     def remove_blank_lines(src)
463:       body = src.text.dup
464:       line = src.lineno
465:       while m = body.slice!(/\A[ \t\f]*(?:\n|\r\n|\r)/)
466:         line += 1
467:       end
468:       SourceText.new(body, src.filename, line)
469:     end
replace_location(src) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 225
225:     def replace_location(src)
226:       sep = make_separator(src)
227:       @f.print 'self.class.' if toplevel?
228:       @f.puts "module_eval(<<'#{sep}', '#{src.filename}', #{src.lineno})"
229:       yield
230:       @f.puts sep
231:     end
require(feature) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 145
145:     def require(feature)
146:       line "require '#{feature}'"
147:     end
runtime_source() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 132
132:     def runtime_source
133:       SourceText.new(::Racc::PARSER_TEXT, 'racc/parser.rb', 1)
134:     end
serialize_integer_list_compressed(name, table) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 330
330:     def serialize_integer_list_compressed(name, table)
331:       sep  = "\n"
332:       nsep = ",\n"
333:       buf  = ''
334:       com  = ''
335:       ncom = ','
336:       co   = com
337:       @f.print 'clist = ['
338:       table.each do |i|
339:         buf << co << i.to_s; co = ncom
340:         if buf.size > 66
341:           @f.print sep; sep = nsep
342:           @f.print "'", buf, "'"
343:           buf = ''
344:           co = com
345:         end
346:       end
347:       unless buf.empty?
348:         @f.print sep
349:         @f.print "'", buf, "'"
350:       end
351:       line ' ]'
352: 
353:       @f.print(        #{name} = arr = Array.new(#{table.size}, nil)        idx = 0        clist.each do |str|          str.split(',', -1).each do |i|            arr[idx] = i.to_i unless i.empty?            idx += 1          end        end)
354:     end
serialize_integer_list_std(name, table) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 365
365:     def serialize_integer_list_std(name, table)
366:       sep = ''
367:       line "#{name} = ["
368:       table.each_slice(10) do |ns|
369:         @f.print sep; sep = ",\n"
370:         @f.print ns.map {|n| sprintf('%6s', n ? n.to_s : 'nil') }.join(',')
371:       end
372:       line ' ]'
373:     end
shebang(path) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 120
120:     def shebang(path)
121:       line '#!' + (path == 'ruby' ? RUBY_PATH : path)
122:     end
state_transition_table() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 261
261:     def state_transition_table
262:       table = @states.state_transition_table
263:       table.use_result_var = @params.result_var?
264:       table.debug_parser = @params.debug_parser?
265: 
266:       line "##### State transition tables begin ###"
267:       line
268:       integer_list 'racc_action_table', table.action_table
269:       line
270:       integer_list 'racc_action_check', table.action_check
271:       line
272:       integer_list 'racc_action_pointer', table.action_pointer
273:       line
274:       integer_list 'racc_action_default', table.action_default
275:       line
276:       integer_list 'racc_goto_table', table.goto_table
277:       line
278:       integer_list 'racc_goto_check', table.goto_check
279:       line
280:       integer_list 'racc_goto_pointer', table.goto_pointer
281:       line
282:       integer_list 'racc_goto_default', table.goto_default
283:       line
284:       i_i_sym_list 'racc_reduce_table', table.reduce_table
285:       line
286:       line "racc_reduce_n = #{table.reduce_n}"
287:       line
288:       line "racc_shift_n = #{table.shift_n}"
289:       line
290:       sym_int_hash 'racc_token_table', table.token_table
291:       line
292:       line "racc_nt_base = #{table.nt_base}"
293:       line
294:       line "racc_use_result_var = #{table.use_result_var}"
295:       line
296:       @f.print(unindent_auto(        Racc_arg = [          racc_action_table,          racc_action_check,          racc_action_default,          racc_action_pointer,          racc_goto_table,          racc_goto_check,          racc_goto_default,          racc_goto_pointer,          racc_nt_base,          racc_reduce_table,          racc_token_table,          racc_shift_n,          racc_reduce_n,          racc_use_result_var ]))
297:       line
298:       string_list 'Racc_token_to_s_table', table.token_to_s_table
299:       line
300:       line "Racc_debug_parser = #{table.debug_parser}"
301:       line
302:       line '##### State transition tables end #####'
303:       actions
304:     end
string_list(name, list) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 395
395:     def string_list(name, list)
396:       sep = "  "
397:       line "#{name} = ["
398:       list.each do |s|
399:         @f.print sep; sep = ",\n  "
400:         @f.print s.dump
401:       end
402:       line ' ]'
403:     end
sym_int_hash(name, h) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 385
385:     def sym_int_hash(name, h)
386:       sep = "\n"
387:       @f.print "#{name} = {"
388:       h.to_a.sort_by {|sym, i| i }.each do |sym, i|
389:         @f.print sep; sep = ",\n"
390:         @f.printf "  %s => %d", sym.serialize, i
391:       end
392:       line " }"
393:     end
toplevel?() click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 221
221:     def toplevel?
222:       @cref.empty?
223:     end
unindent_auto(str) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 479
479:     def unindent_auto(str)
480:       lines = str.to_a
481:       n = minimum_indent(lines)
482:       lines.map {|line| detab(line).sub(indent_re(n), '').rstrip + "\n" }.join('')
483:     end
unique_separator(id) click to toggle source
     # File lib/racc/parserfilegenerator.rb, line 239
239:     def unique_separator(id)
240:       sep = "...end #{id}/module_eval..."
241:       while @used_separator.key?(sep)
242:         sep.concat sprintf('%02x', rand(255))
243:       end
244:       @used_separator[sep] = true
245:       sep
246:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.