# 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
# 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
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
# 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
# File lib/racc/parserfilegenerator.rb, line 213 213: def cref_pop 214: @cref.pop 215: end
# File lib/racc/parserfilegenerator.rb, line 209 209: def cref_push(name) 210: @cref.push name 211: end
# 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
# 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
# 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
# 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
# File lib/racc/parserfilegenerator.rb, line 217 217: def indent 218: @f.print ' ' * @cref.size 219: end
# File lib/racc/parserfilegenerator.rb, line 495 495: def indent_re(n) 496: RE_CACHE[n] ||= /\A {#{n}}/ 497: end
# File lib/racc/parserfilegenerator.rb, line 204 204: def init_line_conversion_system 205: @cref = [] 206: @used_separator = {} 207: end
# 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
# 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
# File lib/racc/parserfilegenerator.rb, line 200 200: def line(str = '') 201: @f.puts str 202: end
# 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
# 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
# File lib/racc/parserfilegenerator.rb, line 485 485: def minimum_indent(lines) 486: lines.map {|line| n_indent(line) }.min 487: end
# File lib/racc/parserfilegenerator.rb, line 489 489: def n_indent(line) 490: line.slice(/\A\s+/).size 491: end
# 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
# 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
# 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
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
# 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
# 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
# File lib/racc/parserfilegenerator.rb, line 145 145: def require(feature) 146: line "require '#{feature}'" 147: end
# File lib/racc/parserfilegenerator.rb, line 132 132: def runtime_source 133: SourceText.new(::Racc::PARSER_TEXT, 'racc/parser.rb', 1) 134: end
# 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
# 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
# File lib/racc/parserfilegenerator.rb, line 120 120: def shebang(path) 121: line '#!' + (path == 'ruby' ? RUBY_PATH : path) 122: end
# 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
# 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
# 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
# File lib/racc/parserfilegenerator.rb, line 221 221: def toplevel? 222: @cref.empty? 223: end
# 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
# 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.
Generated with the Darkfish Rdoc Generator 1.1.6.