Object
# File lib/rexical/generator.rb, line 47 def add_header( st ) @scanner_header += "#{st}\n" end
# File lib/rexical/generator.rb, line 57 def add_inner( st ) @scanner_inner += "#{st}\n" end
# File lib/rexical/generator.rb, line 77 def add_macro( st ) ss = StringScanner.new(st) ss.scan(/\s+/) key = ss.scan(/\S+/) ss.scan(/\s+/) st = ss.post_match len = st.size ndx = 0 while ndx <= len c = st[ndx,1] ndx += 1 case c when '\' ndx += 1 next when '#', ' ' ndx -= 1 break end end expr = st[0,ndx] expr.gsub!('\ ', ' ') key = '{' + key + '}' @macro.each_pair do |k, e| expr.gsub!(k) { |m| e } end @macro[key] = expr rescue raise ParseError, "parse error in add_macro:'#{st}'" end
# File lib/rexical/generator.rb, line 62 def add_option( st ) opts = st.split opts.each do |opt| case opt when /ignorecase/ @opt['--ignorecase'] = true when /stub/ @opt['--stub'] = true when /independent/ @opt['--independent'] = true end end end
# File lib/rexical/generator.rb, line 109 def add_rule( rule_state, rule_expr, rule_action=nil ) st = rule_expr.dup @macro.each_pair do |k, e| rule_expr.gsub!(k) { |m| e } end if rule_state.to_s[1,1] =~ /[A-Z]/ @exclusive_states << rule_state unless @exclusive_states.include?(rule_state) exclusive_state = rule_state start_state = nil else exclusive_state = nil start_state = rule_state end rule = [exclusive_state, start_state, rule_expr, rule_action] @rules << rule rescue raise ParseError, "parse error in add_rule:'#{st}'" end
# File lib/rexical/generator.rb, line 132 def next_line @lineno += 1 @grammar_lines.scan_until(/\n/).chomp rescue nil end
# File lib/rexical/generator.rb, line 139 def parse state1 = :HEAD state2 = nil state3 = nil lastmodes = [] while st = next_line case state1 when :FOOT add_footer st when :HEAD ss = StringScanner.new(st) if ss.scan(/class/) state1 = :CLASS st = ss.post_match.strip @class_name = st else add_header st end when :CLASS s = st.strip next if s.size == 0 or s[0,1] == '#' ss = StringScanner.new(st) if ss.scan(/option.*$/) state2 = :OPTION next end if ss.scan(/inner.*$/) state2 = :INNER next end if ss.scan(/macro.*$/) state2 = :MACRO next end if ss.scan(/rule.*$/) state2 = :RULE next end if ss.scan(/end.*$/) state1 = :FOOT next end case state2 when :OPTION add_option st when :INNER add_inner st when :MACRO add_macro st when :RULE case state3 when nil rule_state, rule_expr, rule_action = parse_rule(st) if rule_action =~ /\s*\{/ lastmodes = parse_action(rule_action, lastmodes) if lastmodes.empty? add_rule rule_state, rule_expr, rule_action else state3 = :CONT rule_action += "\n" end else add_rule rule_state, rule_expr end when :CONT rule_action += "#{st}\n" lastmodes = parse_action(st, lastmodes) if lastmodes.empty? state3 = nil add_rule rule_state, rule_expr, rule_action else end end # case state3 end # case state2 end # case state1 end # while end
# File lib/rexical/generator.rb, line 244 def parse_action(st, lastmodes=[]) modes = lastmodes mode = lastmodes[-1] ss = StringScanner.new(st) until ss.eos? c = ss.scan(/./) case c when '#' if (mode == :brace) or (mode == nil) #p [c, mode, modes] return modes end when '{' if (mode == :brace) or (mode == nil) mode = :brace modes.push mode end when '}' if (mode == :brace) modes.pop mode = modes[0] end when "'" if (mode == :brace) mode = :quote modes.push mode elsif (mode == :quote) modes.pop mode = modes[0] end when '"' if (mode == :brace) mode = :doublequote modes.push mode elsif (mode == :doublequote) modes.pop mode = modes[0] end when '`' if (mode == :brace) mode = :backquote modes.push mode elsif (mode == :backquote) modes.pop mode = modes[0] end end end #p [c, mode, modes] return modes end
# File lib/rexical/generator.rb, line 231 def parse_rule(st) st.strip! return if st.size == 0 or st[0,1] == '#' ss = StringScanner.new(st) ss.scan(/\s+/) rule_state = ss.scan(/\:\S+/) ss.scan(/\s+/) rule_expr = ss.scan(/\S+/) ss.scan(/\s+/) [rule_state, rule_expr, ss.post_match] end
# File lib/rexical/generator.rb, line 128 def read_grammar @grammar_lines = StringScanner.new File.read(grammar_file) end
# File lib/rexical/generator.rb, line 374 def write_scanner f = scanner_io ## scan flag flag = "" flag += "i" if @opt['--ignorecase'] ## header f.printf REX_HEADER, Rexical::VERSION, grammar_file unless @opt['--independent'] f.printf "require 'racc/parser'\n" end @scanner_header.each_line do |s| f.print s end if @opt['--independent'] f.puts "class #{@class_name}" else f.puts "class #{@class_name} < Racc::Parser" end ## utility method f.print REX_UTIL ## scanner method f.print def next_token return if @ss.eos? # skips empty actions until token = _next_token or @ss.eos?; end token end def _next_token text = @ss.peek(1) @lineno += 1 if text == "\\n" token = case @state exclusive_states.each do |es| f.printf when #{es ? es.to_s : "nil"} case rules.each do |rule| exclusive_state, start_state, rule_expr, rule_action = *rule if es == exclusive_state if rule_action if start_state f.print when((state == #{start_state}) and (text = @ss.scan(/#{rule_expr}/#{flag}))) action #{rule_action} else f.print when (text = @ss.scan(/#{rule_expr}/#{flag})) action #{rule_action} end else if start_state f.print when (state == #{start_state}) and (text = @ss.scan(/#{rule_expr}/#{flag})) ; else f.print when (text = @ss.scan(/#{rule_expr}/#{flag})) ; end end end end f.print else text = @ss.string[@ss.pos .. -1] raise ScanError, "can not match: '" + text + "'" end # if end f.print else raise ScanError, "undefined state: '" + state.to_s + "'" end # case state if @opt['--debug'] f.print p token end f.print token end # def _next_token ## inner method @scanner_inner.each_line do |s| f.print s end f.puts "end # class" ## footer @scanner_footer.each_line do |s| f.print s end # case ## stub main f.printf REX_STUB, @class_name, '"%s:%d:%s\n"' if @opt['--stub'] f.close end
Generated with the Darkfish Rdoc Generator 2.