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 455{}
-
RUBY_PATH =
# File 'lib/racc/parserfilegenerator.rb', line 120"#{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
- #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 74
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 224
def toplevel? @cref.empty? end
Instance Method Details
#actions (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 367
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 216
def cref_pop @cref.pop end
#cref_push(name) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 212
def cref_push(name) @cref.push name end
#detab(str, ts = 8) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 461
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 80
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 91
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 220
def indent @f.print ' ' * @cref.size end
#indent_re(n) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 457
def indent_re(n) RE_CACHE[n] ||= /\A {#{n}}/ end
#init_line_conversion_system (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 207
def init_line_conversion_system @cref = [] @used_separator = {} end
#inner (private)
[ GitHub ]#integer_list(name, table) (private)
[ GitHub ]#line(str = '') (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 203
def line(str = '') @f.puts str end
#make_delimiter(body) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 433
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 236
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 ]# File 'lib/racc/parserfilegenerator.rb', line 126
def notice line %q[# frozen_string_literal: true] if @params.frozen_strings? line %q[#] line %q[# DO NOT MODIFY!!!!] line %Q[# This file is automatically generated by Racc #{Racc::Version}] line %Q[# from Racc grammar file "#{@params.filename}".] line %q[#] end
#parser_class(classname, superclass) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 152
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 102
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 193
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 257
def put_state_transition_table(f) @f = f state_transition_table end
#remove_blank_lines(src) (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 424
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 228
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 148
def require(feature) line "require '#{feature}'" end
#runtime_source (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 135
def runtime_source SourceText.new(::Racc::PARSER_TEXT, 'racc/parser.rb', 1) end
#shebang(path) (private)
[ GitHub ]#state_transition_table (private)
[ GitHub ]# File 'lib/racc/parserfilegenerator.rb', line 264
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 "Ractor.make_shareable(Racc_arg) if defined?(Ractor)" line string_list 'Racc_token_to_s_table', table.token_to_s_table line "Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)" 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 347
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 441
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 242
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