Class: Racc::ParserFileGenerator
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Inherits: | Object |
Defined in: | lib/racc/parserfilegenerator.rb |
Constant Summary
-
RE_CACHE =
# File 'lib/racc/parserfilegenerator.rb', line 494{}
-
RUBY_PATH =
# File 'lib/racc/parserfilegenerator.rb', line 118"#{c['bindir']}/#{c['ruby_install_name']}#{c['EXEEXT']}"
Class Method Summary
- .new(states, params) ⇒ ParserFileGenerator constructor
Instance Attribute Summary
- #toplevel? ⇒ Boolean readonly private
Instance Method Summary
- #generate_parser
- #generate_parser_file(destpath)
- #put_state_transition_table(f)
- #actions private
- #cref_pop private
- #cref_push(name) private
- #detab(str, ts = 8) private
- #embed_library(src) private
- #footer private
- #header private
- #i_i_sym_list(name, table) private
- #indent private
- #indent_re(n) private
- #init_line_conversion_system private
- #inner private
- #integer_list(name, table) private
- #line(str = '') private
- #make_delimiter(body) private
- #make_separator(src) private
- #minimum_indent(lines) private
- #n_indent(line) private
- #notice private
- #parser_class(classname, superclass) private
- #parser_file private
-
#put(src, convert_line = false)
private
Low Level Routines.
- #remove_blank_lines(src) private
- #replace_location(src) private
- #require(feature) private
- #runtime_source private
- #serialize_integer_list_compressed(name, table) private
- #serialize_integer_list_std(name, table) private
- #shebang(path) private
- #state_transition_table private
- #string_list(name, list) private
- #sym_int_hash(name, h) private
- #unindent_auto(str) private
- #unique_separator(id) private
Constructor Details
.new(states, params) ⇒ ParserFileGenerator
# File 'lib/racc/parserfilegenerator.rb', line 72
def initialize(states, params) @states = states @grammar = states.grammar @params = params end
Instance Attribute Details
#toplevel? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'lib/racc/parserfilegenerator.rb', line 221
def toplevel? @cref.empty? end
Instance Method Details
#actions (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 406
def actions @grammar.each do |rule| unless rule.action.source? raise "racc: fatal: cannot generate parser file when any action is a Proc" end end if @params.result_var? decl = ', result' retval = "\n result" default_body = '' else decl = '' retval = '' default_body = 'val[0]' end @grammar.each do |rule| line if rule.action.empty? and @params.omit_action_call? line "# reduce #{rule.ident} omitted" else src0 = rule.action.source || SourceText.new(default_body, __FILE__, 0) if @params.convert_line? src = remove_blank_lines(src0) delim = make_delimiter(src.text) @f.printf unindent_auto(<<-End), module_eval(<<'%s', '%s', %d) def _reduce_%d(val, _values%s) %s%s end %s End delim, src.filename, src.lineno - 1, rule.ident, decl, src.text, retval, delim else src = remove_blank_lines(src0) @f.printf unindent_auto(<<-End), def _reduce_%d(val, _values%s) %s%s end End rule.ident, decl, src.text, retval end end end line @f.printf unindent_auto(<<-'End'), decl def _reduce_none(val, _values%s) val[0] end End line end
#cref_pop (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 213
def cref_pop @cref.pop end
#cref_push(name) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 209
def cref_push(name) @cref.push name end
#detab(str, ts = 8) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 500
def detab(str, ts = 8) add = 0 len = nil str.gsub(/\t/) { len = ts - ($`.size + add) % ts add += len - 1 ' ' * len } end
#embed_library(src) (private)
[ GitHub ]#generate_parser
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 78
def generate_parser string_io = StringIO.new init_line_conversion_system @f = string_io parser_file string_io.rewind string_io.read end
#generate_parser_file(destpath)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 89
def generate_parser_file(destpath) init_line_conversion_system File.open(destpath, 'w') {|f| @f = f parser_file } File.chmod 0755, destpath if @params.make_executable? end
#header (private)
[ GitHub ]#i_i_sym_list(name, table) (private)
[ GitHub ]#indent (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 217
def indent @f.print ' ' * @cref.size end
#indent_re(n) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 496
def indent_re(n) RE_CACHE[n] ||= /\A {#{n}}/ end
#init_line_conversion_system (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 204
def init_line_conversion_system @cref = [] @used_separator = {} end
#inner (private)
[ GitHub ]#integer_list(name, table) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 322
def integer_list(name, table) if table.size > 2000 serialize_integer_list_compressed name, table else serialize_integer_list_std name, table end end
#line(str = '') (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 200
def line(str = '') @f.puts str end
#make_delimiter(body) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 472
def make_delimiter(body) delim = '.,.,' while body.index(delim) delim *= 2 end delim end
#make_separator(src) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 233
def make_separator(src) sep = unique_separator(src.filename) sep *= 2 while src.text.index(sep) sep end
#minimum_indent(lines) (private)
[ GitHub ]#n_indent(line) (private)
[ GitHub ]#notice (private)
[ GitHub ]#parser_class(classname, superclass) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 149
def parser_class(classname, superclass) mods = classname.split('::') classid = mods.pop mods.each do |mod| indent; line "module #{mod}" cref_push mod end indent; line "class #{classid} < #{superclass}" cref_push classid yield cref_pop indent; line "end \# class #{classid}" mods.reverse_each do |mod| cref_pop indent; line "end \# module #{mod}" end end
#parser_file (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 100
def parser_file shebang @params.interpreter if @params.make_executable? notice line if @params. runtime_source() else require 'racc/parser.rb' end header parser_class(@params.classname, @params.superclass) { inner state_transition_table } end
#put(src, convert_line = false) (private)
Low Level Routines
# File 'lib/racc/parserfilegenerator.rb', line 190
def put(src, convert_line = false) if convert_line replace_location(src) { @f.puts src.text } else @f.puts src.text end end
#put_state_transition_table(f)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 254
def put_state_transition_table(f) @f = f state_transition_table end
#remove_blank_lines(src) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 463
def remove_blank_lines(src) body = src.text.dup line = src.lineno while body.slice!(/\A[ \t\f]*(?:\n|\r\n|\r)/) line += 1 end SourceText.new(body, src.filename, line) end
#replace_location(src) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 225
def replace_location(src) sep = make_separator(src) @f.print 'self.class.' if toplevel? @f.puts "module_eval(<<'#{sep}', '#{src.filename}', #{src.lineno})" yield @f.puts sep end
#require(feature) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 145
def require(feature) line "require '#{feature}'" end
#runtime_source (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 132
def runtime_source SourceText.new(::Racc::PARSER_TEXT, 'racc/parser.rb', 1) end
#serialize_integer_list_compressed(name, table) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 330
def serialize_integer_list_compressed(name, table) # TODO: this can be made a LOT more clean with a simple split/map sep = "\n" nsep = ",\n" buf = String.new com = '' ncom = ',' co = com @f.print 'clist = [' table.each do |i| buf << co << i.to_s; co = ncom if buf.size > 66 @f.print sep; sep = nsep @f.print "'", buf, "'" buf = String.new co = com end end unless buf.empty? @f.print sep @f.print "'", buf, "'" end line ' ]' @f.print(<<-End) #{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 End end
#serialize_integer_list_std(name, table) (private)
[ GitHub ]#shebang(path) (private)
[ GitHub ]#state_transition_table (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 261
def state_transition_table table = @states.state_transition_table table.use_result_var = @params.result_var? table.debug_parser = @params.debug_parser? line "##### State transition tables begin ###" line integer_list 'racc_action_table', table.action_table line integer_list 'racc_action_check', table.action_check line integer_list 'racc_action_pointer', table.action_pointer line integer_list 'racc_action_default', table.action_default line integer_list 'racc_goto_table', table.goto_table line integer_list 'racc_goto_check', table.goto_check line integer_list 'racc_goto_pointer', table.goto_pointer line integer_list 'racc_goto_default', table.goto_default line i_i_sym_list 'racc_reduce_table', table.reduce_table line line "racc_reduce_n = #{table.reduce_n}" line line "racc_shift_n = #{table.shift_n}" line sym_int_hash 'racc_token_table', table.token_table line line "racc_nt_base = #{table.nt_base}" line line "racc_use_result_var = #{table.use_result_var}" line @f.print(unindent_auto(<<-End)) 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 ] End line string_list 'Racc_token_to_s_table', table.token_to_s_table line line "Racc_debug_parser = #{table.debug_parser}" line line '##### State transition tables end #####' actions end
#string_list(name, list) (private)
[ GitHub ]#sym_int_hash(name, h) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 386
def sym_int_hash(name, h) sep = "\n" @f.print "#{name} = {" h.to_a.sort_by {|sym, i| i }.each do |sym, i| @f.print sep; sep = ",\n" @f.printf " %s => %d", sym.serialize, i end line " }" end
#unindent_auto(str) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 480
def unindent_auto(str) lines = str.lines.to_a n = minimum_indent(lines) lines.map {|line| detab(line).sub(indent_re(n), '').rstrip + "\n" }.join('') end
#unique_separator(id) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 239
def unique_separator(id) sep = String.new "...end #{id}/module_eval..." while @used_separator.key?(sep) sep.concat sprintf('%02x', rand(255)) end @used_separator[sep] = true sep end