From bc3d249b6f8a707a71aa75a413894564b88c7d09 Mon Sep 17 00:00:00 2001 From: Yura Sokolov Date: Sun, 13 Aug 2023 16:19:21 +0300 Subject: [PATCH 1/3] make examples refreshable with `rake examples` and `rake test` --- Rakefile | 20 +- examples/calculator/calculator.kpeg.rb | 664 ++++++++++++++++ examples/foreign_reference/literals.kpeg.rb | 420 ++++++++++ examples/foreign_reference/matcher.kpeg.rb | 471 +++++++++++ examples/lua_string/lua_string.kpeg.rb | 262 ++++--- examples/phone_number/phone_number.kpeg.rb | 772 +++++++++++++++++++ examples/tiny_markdown/tiny_markdown.kpeg.rb | 138 ++-- examples/upper/upper.kpeg.rb | 701 +++++++++++++++++ 8 files changed, 3304 insertions(+), 144 deletions(-) create mode 100644 examples/calculator/calculator.kpeg.rb create mode 100644 examples/foreign_reference/literals.kpeg.rb create mode 100644 examples/foreign_reference/matcher.kpeg.rb create mode 100644 examples/phone_number/phone_number.kpeg.rb create mode 100644 examples/upper/upper.kpeg.rb diff --git a/Rakefile b/Rakefile index ec17c2d..bf27c79 100644 --- a/Rakefile +++ b/Rakefile @@ -23,21 +23,39 @@ rule ".rb" => ".kpeg" do |t| ruby "-Ilib bin/kpeg -s -o #{t.name} -f #{t.source}" end +rule ".kpeg.rb" => ".kpeg" do |t| + ruby "-Ilib bin/kpeg -s -o #{t.name} -f #{t.source}" +end + PARSER_FILES = %w[ lib/kpeg/string_escape.rb lib/kpeg/format_parser.rb ] -PARSER_FILES.map do |parser_file| +PARSER_FILES.each do |parser_file| file parser_file => 'lib/kpeg/compiled_parser.rb' file parser_file => 'lib/kpeg/code_generator.rb' file parser_file => 'lib/kpeg/position.rb' file parser_file => parser_file.sub(/\.rb$/, '.kpeg') end +EXAMPLE_FILES = Dir.glob('examples/*/*.kpeg').map{|f| f + ".rb" } + +EXAMPLE_FILES.each do |example_file| + file example_file => 'lib/kpeg/compiled_parser.rb' + file example_file => 'lib/kpeg/code_generator.rb' + file example_file => 'lib/kpeg/position.rb' + file example_file => example_file.sub(/\.rb$/, '') +end + desc "build the parser" task :parser => PARSER_FILES +desc "build the examples" +task :examples => EXAMPLE_FILES + +task :test => :examples + task :gem do sh "gem build" end diff --git a/examples/calculator/calculator.kpeg.rb b/examples/calculator/calculator.kpeg.rb new file mode 100644 index 0000000..0af26ee --- /dev/null +++ b/examples/calculator/calculator.kpeg.rb @@ -0,0 +1,664 @@ +class Calculator + # :stopdoc: + + # This is distinct from setup_parser so that a standalone parser + # can redefine #initialize and still have access to the proper + # parser setup code. + def initialize(str, debug=false) + setup_parser(str, debug) + end + + + + # Prepares for parsing +str+. If you define a custom initialize you must + # call this method before #parse + def setup_parser(str, debug=false) + set_string str, 0 + @memoizations = Hash.new { |h,k| h[k] = {} } + @result = nil + @failed_rule = nil + @failing_rule_offset = -1 + @line_offsets = nil + + setup_foreign_grammar + end + + attr_reader :string + attr_reader :failing_rule_offset + attr_accessor :result, :pos + + def current_column(target=pos) + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c + end + + target + 1 + end + + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end + + if [].respond_to? :bsearch_index + def current_line(target=pos) + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 + end + raise "Target position #{target} is outside of string" + end + else + def current_line(target=pos) + if line = position_line_offsets.index {|x| x > target } + return line + 1 + end + + raise "Target position #{target} is outside of string" + end + end + + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) + end + + def lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] + end + + + + def get_text(start) + @string[start..@pos-1] + end + + # Sets the string and current parsing position for the parser. + def set_string string, pos + @string = string + @string_size = string ? string.size : 0 + @pos = pos + @position_line_offsets = nil + end + + def show_pos + width = 10 + if @pos < width + "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" + else + "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" + end + end + + def failure_info + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" + else + "line #{l}, column #{c}: failed rule '#{@failed_rule}'" + end + end + + def failure_caret + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" + end + + def failure_character + current_character @failing_rule_offset + end + + def failure_oneline + p = current_pos_info @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" + else + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" + end + end + + class ParseError < RuntimeError + end + + def raise_error + raise ParseError, failure_oneline + end + + def show_error(io=STDOUT) + error_pos = @failing_rule_offset + p = current_pos_info(error_pos) + + io.puts "On line #{p.lno}, column #{p.col}:" + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" + else + io.puts "Failed to match rule '#{@failed_rule}'" + end + + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) + io.puts "^" + end + + def set_failed_rule(name) + if @pos > @failing_rule_offset + @failed_rule = name + @failing_rule_offset = @pos + end + end + + attr_reader :failed_rule + + def match_string(str) + len = str.size + if @string[pos,len] == str + @pos += len + return str + end + + return nil + end + + def scan(reg) + if m = reg.match(@string, @pos) + @pos = m.end(0) + return true + end + + return nil + end + + if "".respond_to? :ord + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos].ord + @pos += 1 + s + end + else + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos] + @pos += 1 + s + end + end + + def parse(rule=nil) + # We invoke the rules indirectly via apply + # instead of by just calling them as methods because + # if the rules use left recursion, apply needs to + # manage that. + + if !rule + apply(:_root) + else + method = rule.gsub("-","_hyphen_") + apply :"_#{method}" + end + end + + class MemoEntry + def initialize(ans, pos) + @ans = ans + @pos = pos + @result = nil + @set = false + @left_rec = false + end + + attr_reader :ans, :pos, :result, :set + attr_accessor :left_rec + + def move!(ans, pos, result) + @ans = ans + @pos = pos + @result = result + @set = true + @left_rec = false + end + end + + def external_invoke(other, rule, *args) + old_pos = @pos + old_string = @string + + set_string other.string, other.pos + + begin + if val = __send__(rule, *args) + other.pos = @pos + other.result = @result + else + other.set_failed_rule "#{self.class}##{rule}" + end + val + ensure + set_string old_string, old_pos + end + end + + def apply_with_args(rule, *args) + @result = nil + memo_key = [rule, args] + if m = @memoizations[memo_key][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[memo_key][@pos] = m + start_pos = @pos + + ans = __send__ rule, *args + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, args, start_pos, m) + else + return ans + end + end + end + + def apply(rule) + @result = nil + if m = @memoizations[rule][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[rule][@pos] = m + start_pos = @pos + + ans = __send__ rule + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, nil, start_pos, m) + else + return ans + end + end + end + + def grow_lr(rule, args, start_pos, m) + while true + @pos = start_pos + @result = m.result + + if args + ans = __send__ rule, *args + else + ans = __send__ rule + end + return nil unless ans + + break if @pos <= m.pos + + m.move! ans, @pos, @result + end + + @result = m.result + @pos = m.pos + return m.ans + end + + class RuleInfo + def initialize(name, rendered) + @name = name + @rendered = rendered + end + + attr_reader :name, :rendered + end + + def self.rule_info(name, rendered) + RuleInfo.new(name, rendered) + end + + + # :startdoc: + + + attr_accessor :result + + + # :stopdoc: + def setup_foreign_grammar; end + + # space = " " + def _space + _tmp = match_string(" ") + set_failed_rule :_space unless _tmp + return _tmp + end + + # - = space* + def __hyphen_ + while true + _tmp = apply(:_space) + break unless _tmp + end + _tmp = true + set_failed_rule :__hyphen_ unless _tmp + return _tmp + end + + # num = < /[1-9][0-9]*/ > { text.to_i } + def _num + + _save = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\G(?-mix:[1-9][0-9]*)/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text.to_i ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_num unless _tmp + return _tmp + end + + # term = (term:t1 - "+" - term:t2 { t1 + t2 } | term:t1 - "-" - term:t2 { t1 - t2 } | fact) + def _term + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_term) + t1 = @result + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save1 + break + end + _tmp = match_string("+") + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_term) + t2 = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; t1 + t2 ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = apply(:_term) + t1 = @result + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save2 + break + end + _tmp = match_string("-") + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_term) + t2 = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; t1 - t2 ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + _tmp = apply(:_fact) + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_term unless _tmp + return _tmp + end + + # fact = (fact:f1 - "*" - fact:f2 { f1 * f2 } | fact:f1 - "/" - fact:f2 { f1 / f2 } | num) + def _fact + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_fact) + f1 = @result + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save1 + break + end + _tmp = match_string("*") + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_fact) + f2 = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; f1 * f2 ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = apply(:_fact) + f1 = @result + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save2 + break + end + _tmp = match_string("/") + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:__hyphen_) + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_fact) + f2 = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; f1 / f2 ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + _tmp = apply(:_num) + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_fact unless _tmp + return _tmp + end + + # root = term:t { @result = t } + def _root + + _save = self.pos + while true # sequence + _tmp = apply(:_term) + t = @result + unless _tmp + self.pos = _save + break + end + @result = begin; @result = t ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_root unless _tmp + return _tmp + end + + Rules = {} + Rules[:_space] = rule_info("space", "\" \"") + Rules[:__hyphen_] = rule_info("-", "space*") + Rules[:_num] = rule_info("num", "< /[1-9][0-9]*/ > { text.to_i }") + Rules[:_term] = rule_info("term", "(term:t1 - \"+\" - term:t2 { t1 + t2 } | term:t1 - \"-\" - term:t2 { t1 - t2 } | fact)") + Rules[:_fact] = rule_info("fact", "(fact:f1 - \"*\" - fact:f2 { f1 * f2 } | fact:f1 - \"/\" - fact:f2 { f1 / f2 } | num)") + Rules[:_root] = rule_info("root", "term:t { @result = t }") + # :startdoc: +end diff --git a/examples/foreign_reference/literals.kpeg.rb b/examples/foreign_reference/literals.kpeg.rb new file mode 100644 index 0000000..4ebdbff --- /dev/null +++ b/examples/foreign_reference/literals.kpeg.rb @@ -0,0 +1,420 @@ +class Literal + # :stopdoc: + + # This is distinct from setup_parser so that a standalone parser + # can redefine #initialize and still have access to the proper + # parser setup code. + def initialize(str, debug=false) + setup_parser(str, debug) + end + + + + # Prepares for parsing +str+. If you define a custom initialize you must + # call this method before #parse + def setup_parser(str, debug=false) + set_string str, 0 + @memoizations = Hash.new { |h,k| h[k] = {} } + @result = nil + @failed_rule = nil + @failing_rule_offset = -1 + @line_offsets = nil + + setup_foreign_grammar + end + + attr_reader :string + attr_reader :failing_rule_offset + attr_accessor :result, :pos + + def current_column(target=pos) + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c + end + + target + 1 + end + + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end + + if [].respond_to? :bsearch_index + def current_line(target=pos) + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 + end + raise "Target position #{target} is outside of string" + end + else + def current_line(target=pos) + if line = position_line_offsets.index {|x| x > target } + return line + 1 + end + + raise "Target position #{target} is outside of string" + end + end + + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) + end + + def lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] + end + + + + def get_text(start) + @string[start..@pos-1] + end + + # Sets the string and current parsing position for the parser. + def set_string string, pos + @string = string + @string_size = string ? string.size : 0 + @pos = pos + @position_line_offsets = nil + end + + def show_pos + width = 10 + if @pos < width + "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" + else + "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" + end + end + + def failure_info + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" + else + "line #{l}, column #{c}: failed rule '#{@failed_rule}'" + end + end + + def failure_caret + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" + end + + def failure_character + current_character @failing_rule_offset + end + + def failure_oneline + p = current_pos_info @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" + else + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" + end + end + + class ParseError < RuntimeError + end + + def raise_error + raise ParseError, failure_oneline + end + + def show_error(io=STDOUT) + error_pos = @failing_rule_offset + p = current_pos_info(error_pos) + + io.puts "On line #{p.lno}, column #{p.col}:" + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" + else + io.puts "Failed to match rule '#{@failed_rule}'" + end + + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) + io.puts "^" + end + + def set_failed_rule(name) + if @pos > @failing_rule_offset + @failed_rule = name + @failing_rule_offset = @pos + end + end + + attr_reader :failed_rule + + def match_string(str) + len = str.size + if @string[pos,len] == str + @pos += len + return str + end + + return nil + end + + def scan(reg) + if m = reg.match(@string, @pos) + @pos = m.end(0) + return true + end + + return nil + end + + if "".respond_to? :ord + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos].ord + @pos += 1 + s + end + else + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos] + @pos += 1 + s + end + end + + def parse(rule=nil) + # We invoke the rules indirectly via apply + # instead of by just calling them as methods because + # if the rules use left recursion, apply needs to + # manage that. + + if !rule + apply(:_root) + else + method = rule.gsub("-","_hyphen_") + apply :"_#{method}" + end + end + + class MemoEntry + def initialize(ans, pos) + @ans = ans + @pos = pos + @result = nil + @set = false + @left_rec = false + end + + attr_reader :ans, :pos, :result, :set + attr_accessor :left_rec + + def move!(ans, pos, result) + @ans = ans + @pos = pos + @result = result + @set = true + @left_rec = false + end + end + + def external_invoke(other, rule, *args) + old_pos = @pos + old_string = @string + + set_string other.string, other.pos + + begin + if val = __send__(rule, *args) + other.pos = @pos + other.result = @result + else + other.set_failed_rule "#{self.class}##{rule}" + end + val + ensure + set_string old_string, old_pos + end + end + + def apply_with_args(rule, *args) + @result = nil + memo_key = [rule, args] + if m = @memoizations[memo_key][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[memo_key][@pos] = m + start_pos = @pos + + ans = __send__ rule, *args + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, args, start_pos, m) + else + return ans + end + end + end + + def apply(rule) + @result = nil + if m = @memoizations[rule][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[rule][@pos] = m + start_pos = @pos + + ans = __send__ rule + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, nil, start_pos, m) + else + return ans + end + end + end + + def grow_lr(rule, args, start_pos, m) + while true + @pos = start_pos + @result = m.result + + if args + ans = __send__ rule, *args + else + ans = __send__ rule + end + return nil unless ans + + break if @pos <= m.pos + + m.move! ans, @pos, @result + end + + @result = m.result + @pos = m.pos + return m.ans + end + + class RuleInfo + def initialize(name, rendered) + @name = name + @rendered = rendered + end + + attr_reader :name, :rendered + end + + def self.rule_info(name, rendered) + RuleInfo.new(name, rendered) + end + + + # :startdoc: + # :stopdoc: + def setup_foreign_grammar; end + + # period = "." + def _period + _tmp = match_string(".") + set_failed_rule :_period unless _tmp + return _tmp + end + + # space = " " + def _space + _tmp = match_string(" ") + set_failed_rule :_space unless _tmp + return _tmp + end + + # alpha = /[A-Za-z]/ + def _alpha + _tmp = scan(/\G(?-mix:[A-Za-z])/) + set_failed_rule :_alpha unless _tmp + return _tmp + end + + Rules = {} + Rules[:_period] = rule_info("period", "\".\"") + Rules[:_space] = rule_info("space", "\" \"") + Rules[:_alpha] = rule_info("alpha", "/[A-Za-z]/") + # :startdoc: +end diff --git a/examples/foreign_reference/matcher.kpeg.rb b/examples/foreign_reference/matcher.kpeg.rb new file mode 100644 index 0000000..7e308ee --- /dev/null +++ b/examples/foreign_reference/matcher.kpeg.rb @@ -0,0 +1,471 @@ +class Matcher + # :stopdoc: + + # This is distinct from setup_parser so that a standalone parser + # can redefine #initialize and still have access to the proper + # parser setup code. + def initialize(str, debug=false) + setup_parser(str, debug) + end + + + + # Prepares for parsing +str+. If you define a custom initialize you must + # call this method before #parse + def setup_parser(str, debug=false) + set_string str, 0 + @memoizations = Hash.new { |h,k| h[k] = {} } + @result = nil + @failed_rule = nil + @failing_rule_offset = -1 + @line_offsets = nil + + setup_foreign_grammar + end + + attr_reader :string + attr_reader :failing_rule_offset + attr_accessor :result, :pos + + def current_column(target=pos) + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c + end + + target + 1 + end + + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end + + if [].respond_to? :bsearch_index + def current_line(target=pos) + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 + end + raise "Target position #{target} is outside of string" + end + else + def current_line(target=pos) + if line = position_line_offsets.index {|x| x > target } + return line + 1 + end + + raise "Target position #{target} is outside of string" + end + end + + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) + end + + def lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] + end + + + + def get_text(start) + @string[start..@pos-1] + end + + # Sets the string and current parsing position for the parser. + def set_string string, pos + @string = string + @string_size = string ? string.size : 0 + @pos = pos + @position_line_offsets = nil + end + + def show_pos + width = 10 + if @pos < width + "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" + else + "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" + end + end + + def failure_info + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" + else + "line #{l}, column #{c}: failed rule '#{@failed_rule}'" + end + end + + def failure_caret + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" + end + + def failure_character + current_character @failing_rule_offset + end + + def failure_oneline + p = current_pos_info @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" + else + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" + end + end + + class ParseError < RuntimeError + end + + def raise_error + raise ParseError, failure_oneline + end + + def show_error(io=STDOUT) + error_pos = @failing_rule_offset + p = current_pos_info(error_pos) + + io.puts "On line #{p.lno}, column #{p.col}:" + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" + else + io.puts "Failed to match rule '#{@failed_rule}'" + end + + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) + io.puts "^" + end + + def set_failed_rule(name) + if @pos > @failing_rule_offset + @failed_rule = name + @failing_rule_offset = @pos + end + end + + attr_reader :failed_rule + + def match_string(str) + len = str.size + if @string[pos,len] == str + @pos += len + return str + end + + return nil + end + + def scan(reg) + if m = reg.match(@string, @pos) + @pos = m.end(0) + return true + end + + return nil + end + + if "".respond_to? :ord + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos].ord + @pos += 1 + s + end + else + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos] + @pos += 1 + s + end + end + + def parse(rule=nil) + # We invoke the rules indirectly via apply + # instead of by just calling them as methods because + # if the rules use left recursion, apply needs to + # manage that. + + if !rule + apply(:_root) + else + method = rule.gsub("-","_hyphen_") + apply :"_#{method}" + end + end + + class MemoEntry + def initialize(ans, pos) + @ans = ans + @pos = pos + @result = nil + @set = false + @left_rec = false + end + + attr_reader :ans, :pos, :result, :set + attr_accessor :left_rec + + def move!(ans, pos, result) + @ans = ans + @pos = pos + @result = result + @set = true + @left_rec = false + end + end + + def external_invoke(other, rule, *args) + old_pos = @pos + old_string = @string + + set_string other.string, other.pos + + begin + if val = __send__(rule, *args) + other.pos = @pos + other.result = @result + else + other.set_failed_rule "#{self.class}##{rule}" + end + val + ensure + set_string old_string, old_pos + end + end + + def apply_with_args(rule, *args) + @result = nil + memo_key = [rule, args] + if m = @memoizations[memo_key][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[memo_key][@pos] = m + start_pos = @pos + + ans = __send__ rule, *args + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, args, start_pos, m) + else + return ans + end + end + end + + def apply(rule) + @result = nil + if m = @memoizations[rule][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[rule][@pos] = m + start_pos = @pos + + ans = __send__ rule + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, nil, start_pos, m) + else + return ans + end + end + end + + def grow_lr(rule, args, start_pos, m) + while true + @pos = start_pos + @result = m.result + + if args + ans = __send__ rule, *args + else + ans = __send__ rule + end + return nil unless ans + + break if @pos <= m.pos + + m.move! ans, @pos, @result + end + + @result = m.result + @pos = m.pos + return m.ans + end + + class RuleInfo + def initialize(name, rendered) + @name = name + @rendered = rendered + end + + attr_reader :name, :rendered + end + + def self.rule_info(name, rendered) + RuleInfo.new(name, rendered) + end + + + # :startdoc: + + + require "literals.kpeg.rb" + + + # :stopdoc: + def setup_foreign_grammar + @_grammar_grammer1 = Literal.new(nil) + end + + # root = (%grammer1.alpha %grammer1.space*)+ %grammer1.period + def _root + + _save = self.pos + while true # sequence + _save1 = self.pos + + _save2 = self.pos + while true # sequence + _tmp = @_grammar_grammer1.external_invoke(self, :_alpha) + unless _tmp + self.pos = _save2 + break + end + while true + _tmp = @_grammar_grammer1.external_invoke(self, :_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + if _tmp + while true + + _save4 = self.pos + while true # sequence + _tmp = @_grammar_grammer1.external_invoke(self, :_alpha) + unless _tmp + self.pos = _save4 + break + end + while true + _tmp = @_grammar_grammer1.external_invoke(self, :_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break unless _tmp + end + _tmp = true + else + self.pos = _save1 + end + unless _tmp + self.pos = _save + break + end + _tmp = @_grammar_grammer1.external_invoke(self, :_period) + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_root unless _tmp + return _tmp + end + + Rules = {} + Rules[:_root] = rule_info("root", "(%grammer1.alpha %grammer1.space*)+ %grammer1.period") + # :startdoc: +end diff --git a/examples/lua_string/lua_string.kpeg.rb b/examples/lua_string/lua_string.kpeg.rb index bc3ffdf..42cf1fd 100644 --- a/examples/lua_string/lua_string.kpeg.rb +++ b/examples/lua_string/lua_string.kpeg.rb @@ -1,62 +1,118 @@ class LuaString -# STANDALONE START + # :stopdoc: + + # This is distinct from setup_parser so that a standalone parser + # can redefine #initialize and still have access to the proper + # parser setup code. + def initialize(str, debug=false) + setup_parser(str, debug) + end + + + + # Prepares for parsing +str+. If you define a custom initialize you must + # call this method before #parse def setup_parser(str, debug=false) - @string = str - @pos = 0 + set_string str, 0 @memoizations = Hash.new { |h,k| h[k] = {} } @result = nil @failed_rule = nil @failing_rule_offset = -1 + @line_offsets = nil setup_foreign_grammar end - # This is distinct from setup_parser so that a standalone parser - # can redefine #initialize and still have access to the proper - # parser setup code. - # - def initialize(str, debug=false) - setup_parser(str, debug) - end - attr_reader :string - attr_reader :result, :failing_rule_offset - attr_accessor :pos + attr_reader :failing_rule_offset + attr_accessor :result, :pos - # STANDALONE START def current_column(target=pos) - if c = string.rindex("\n", target-1) - return target - c - 1 + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c end target + 1 end - def current_line(target=pos) - cur_offset = 0 - cur_line = 0 + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end - string.each_line do |line| - cur_line += 1 - cur_offset += line.size - return cur_line if cur_offset >= target + if [].respond_to? :bsearch_index + def current_line(target=pos) + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 + end + raise "Target position #{target} is outside of string" end + else + def current_line(target=pos) + if line = position_line_offsets.index {|x| x > target } + return line + 1 + end + + raise "Target position #{target} is outside of string" + end + end - -1 + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) end def lines - lines = [] - string.each_line { |l| lines << l } - lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] end - # + def get_text(start) @string[start..@pos-1] end + # Sets the string and current parsing position for the parser. + def set_string string, pos + @string = string + @string_size = string ? string.size : 0 + @pos = pos + @position_line_offsets = nil + end + def show_pos width = 10 if @pos < width @@ -79,30 +135,22 @@ def failure_info end def failure_caret - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - line = lines[l-1] - "#{line}\n#{' ' * (c - 1)}^" + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" end def failure_character - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - lines[l-1][c-1, 1] + current_character @failing_rule_offset end def failure_oneline - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - char = lines[l-1][c-1, 1] + p = current_pos_info @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] - "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" else - "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" end end @@ -115,10 +163,9 @@ def raise_error def show_error(io=STDOUT) error_pos = @failing_rule_offset - line_no = current_line(error_pos) - col_no = current_column(error_pos) + p = current_pos_info(error_pos) - io.puts "On line #{line_no}, column #{col_no}:" + io.puts "On line #{p.lno}, column #{p.col}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] @@ -127,10 +174,9 @@ def show_error(io=STDOUT) io.puts "Failed to match rule '#{@failed_rule}'" end - io.puts "Got: #{string[error_pos,1].inspect}" - line = lines[line_no-1] - io.puts "=> #{line}" - io.print(" " * (col_no + 3)) + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) io.puts "^" end @@ -154,28 +200,27 @@ def match_string(str) end def scan(reg) - if m = reg.match(@string[@pos..-1]) - width = m.end(0) - @pos += width + if m = reg.match(@string, @pos) + @pos = m.end(0) return true end return nil end - if "".respond_to? :getbyte + if "".respond_to? :ord def get_byte - if @pos >= @string.size + if @pos >= @string_size return nil end - s = @string.getbyte @pos + s = @string[@pos].ord @pos += 1 s end else def get_byte - if @pos >= @string.size + if @pos >= @string_size return nil end @@ -186,41 +231,37 @@ def get_byte end def parse(rule=nil) + # We invoke the rules indirectly via apply + # instead of by just calling them as methods because + # if the rules use left recursion, apply needs to + # manage that. + if !rule - _root ? true : false + apply(:_root) else - # This is not shared with code_generator.rb so this can be standalone method = rule.gsub("-","_hyphen_") - __send__("_#{method}") ? true : false - end - end - - class LeftRecursive - def initialize(detected=false) - @detected = detected + apply :"_#{method}" end - - attr_accessor :detected end class MemoEntry def initialize(ans, pos) @ans = ans @pos = pos - @uses = 1 @result = nil + @set = false + @left_rec = false end - attr_reader :ans, :pos, :uses, :result - - def inc! - @uses += 1 - end + attr_reader :ans, :pos, :result, :set + attr_accessor :left_rec def move!(ans, pos, result) @ans = ans @pos = pos @result = result + @set = true + @left_rec = false end end @@ -228,30 +269,61 @@ def external_invoke(other, rule, *args) old_pos = @pos old_string = @string - @pos = other.pos - @string = other.string + set_string other.string, other.pos begin if val = __send__(rule, *args) other.pos = @pos + other.result = @result else other.set_failed_rule "#{self.class}##{rule}" end val ensure - @pos = old_pos - @string = old_string + set_string old_string, old_pos + end + end + + def apply_with_args(rule, *args) + @result = nil + memo_key = [rule, args] + if m = @memoizations[memo_key][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[memo_key][@pos] = m + start_pos = @pos + + ans = __send__ rule, *args + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, args, start_pos, m) + else + return ans + end end end def apply(rule) + @result = nil if m = @memoizations[rule][@pos] - m.inc! - - prev = @pos @pos = m.pos - if m.ans.kind_of? LeftRecursive - m.ans.detected = true + if !m.set + m.left_rec = true return nil end @@ -259,31 +331,36 @@ def apply(rule) return m.ans else - lr = LeftRecursive.new(false) - m = MemoEntry.new(lr, @pos) + m = MemoEntry.new(nil, @pos) @memoizations[rule][@pos] = m start_pos = @pos ans = __send__ rule + lr = m.left_rec + m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) - if ans and lr.detected - return grow_lr(rule, start_pos, m) + if ans and lr + return grow_lr(rule, nil, start_pos, m) else return ans end end end - def grow_lr(rule, start_pos, m) + def grow_lr(rule, args, start_pos, m) while true @pos = start_pos @result = m.result - ans = __send__ rule + if args + ans = __send__ rule, *args + else + ans = __send__ rule + end return nil unless ans break if @pos <= m.pos @@ -309,12 +386,14 @@ def self.rule_info(name, rendered) RuleInfo.new(name, rendered) end - # + + # :startdoc: attr_accessor :result + # :stopdoc: def setup_foreign_grammar; end # equals = < "="* > { text } @@ -408,7 +487,7 @@ def _root _save2 = self.pos while true # sequence _save3 = self.pos - _tmp = _equal_ending(e) + _tmp = apply_with_args(:_equal_ending, e) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp @@ -432,7 +511,7 @@ def _root self.pos = _save break end - _tmp = _equal_ending(e) + _tmp = apply_with_args(:_equal_ending, e) unless _tmp self.pos = _save break @@ -455,4 +534,5 @@ def _root Rules[:_equals] = rule_info("equals", "< \"=\"* > { text }") Rules[:_equal_ending] = rule_info("equal_ending", "\"]\" equals:x &{ x == start } \"]\"") Rules[:_root] = rule_info("root", "\"[\" equals:e \"[\" < (!equal_ending(e) .)* > equal_ending(e) { @result = text }") + # :startdoc: end diff --git a/examples/phone_number/phone_number.kpeg.rb b/examples/phone_number/phone_number.kpeg.rb new file mode 100644 index 0000000..1a47588 --- /dev/null +++ b/examples/phone_number/phone_number.kpeg.rb @@ -0,0 +1,772 @@ +class PhoneNumber + # :stopdoc: + + # This is distinct from setup_parser so that a standalone parser + # can redefine #initialize and still have access to the proper + # parser setup code. + def initialize(str, debug=false) + setup_parser(str, debug) + end + + + + # Prepares for parsing +str+. If you define a custom initialize you must + # call this method before #parse + def setup_parser(str, debug=false) + set_string str, 0 + @memoizations = Hash.new { |h,k| h[k] = {} } + @result = nil + @failed_rule = nil + @failing_rule_offset = -1 + @line_offsets = nil + + setup_foreign_grammar + end + + attr_reader :string + attr_reader :failing_rule_offset + attr_accessor :result, :pos + + def current_column(target=pos) + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c + end + + target + 1 + end + + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end + + if [].respond_to? :bsearch_index + def current_line(target=pos) + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 + end + raise "Target position #{target} is outside of string" + end + else + def current_line(target=pos) + if line = position_line_offsets.index {|x| x > target } + return line + 1 + end + + raise "Target position #{target} is outside of string" + end + end + + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) + end + + def lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] + end + + + + def get_text(start) + @string[start..@pos-1] + end + + # Sets the string and current parsing position for the parser. + def set_string string, pos + @string = string + @string_size = string ? string.size : 0 + @pos = pos + @position_line_offsets = nil + end + + def show_pos + width = 10 + if @pos < width + "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" + else + "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" + end + end + + def failure_info + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" + else + "line #{l}, column #{c}: failed rule '#{@failed_rule}'" + end + end + + def failure_caret + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" + end + + def failure_character + current_character @failing_rule_offset + end + + def failure_oneline + p = current_pos_info @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" + else + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" + end + end + + class ParseError < RuntimeError + end + + def raise_error + raise ParseError, failure_oneline + end + + def show_error(io=STDOUT) + error_pos = @failing_rule_offset + p = current_pos_info(error_pos) + + io.puts "On line #{p.lno}, column #{p.col}:" + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" + else + io.puts "Failed to match rule '#{@failed_rule}'" + end + + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) + io.puts "^" + end + + def set_failed_rule(name) + if @pos > @failing_rule_offset + @failed_rule = name + @failing_rule_offset = @pos + end + end + + attr_reader :failed_rule + + def match_string(str) + len = str.size + if @string[pos,len] == str + @pos += len + return str + end + + return nil + end + + def scan(reg) + if m = reg.match(@string, @pos) + @pos = m.end(0) + return true + end + + return nil + end + + if "".respond_to? :ord + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos].ord + @pos += 1 + s + end + else + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos] + @pos += 1 + s + end + end + + def parse(rule=nil) + # We invoke the rules indirectly via apply + # instead of by just calling them as methods because + # if the rules use left recursion, apply needs to + # manage that. + + if !rule + apply(:_root) + else + method = rule.gsub("-","_hyphen_") + apply :"_#{method}" + end + end + + class MemoEntry + def initialize(ans, pos) + @ans = ans + @pos = pos + @result = nil + @set = false + @left_rec = false + end + + attr_reader :ans, :pos, :result, :set + attr_accessor :left_rec + + def move!(ans, pos, result) + @ans = ans + @pos = pos + @result = result + @set = true + @left_rec = false + end + end + + def external_invoke(other, rule, *args) + old_pos = @pos + old_string = @string + + set_string other.string, other.pos + + begin + if val = __send__(rule, *args) + other.pos = @pos + other.result = @result + else + other.set_failed_rule "#{self.class}##{rule}" + end + val + ensure + set_string old_string, old_pos + end + end + + def apply_with_args(rule, *args) + @result = nil + memo_key = [rule, args] + if m = @memoizations[memo_key][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[memo_key][@pos] = m + start_pos = @pos + + ans = __send__ rule, *args + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, args, start_pos, m) + else + return ans + end + end + end + + def apply(rule) + @result = nil + if m = @memoizations[rule][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[rule][@pos] = m + start_pos = @pos + + ans = __send__ rule + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, nil, start_pos, m) + else + return ans + end + end + end + + def grow_lr(rule, args, start_pos, m) + while true + @pos = start_pos + @result = m.result + + if args + ans = __send__ rule, *args + else + ans = __send__ rule + end + return nil unless ans + + break if @pos <= m.pos + + m.move! ans, @pos, @result + end + + @result = m.result + @pos = m.pos + return m.ans + end + + class RuleInfo + def initialize(name, rendered) + @name = name + @rendered = rendered + end + + attr_reader :name, :rendered + end + + def self.rule_info(name, rendered) + RuleInfo.new(name, rendered) + end + + + # :startdoc: + + + attr_accessor :phone_number + + + # :stopdoc: + def setup_foreign_grammar; end + + # digit = [0-9] + def _digit + _save = self.pos + _tmp = get_byte + if _tmp + unless _tmp >= 48 and _tmp <= 57 + self.pos = _save + _tmp = nil + end + end + set_failed_rule :_digit unless _tmp + return _tmp + end + + # space = " " + def _space + _tmp = match_string(" ") + set_failed_rule :_space unless _tmp + return _tmp + end + + # dash = "-" + def _dash + _tmp = match_string("-") + set_failed_rule :_dash unless _tmp + return _tmp + end + + # LP = "(" + def _LP + _tmp = match_string("(") + set_failed_rule :_LP unless _tmp + return _tmp + end + + # RP = ")" + def _RP + _tmp = match_string(")") + set_failed_rule :_RP unless _tmp + return _tmp + end + + # country_code = < digit > { text } + def _country_code + + _save = self.pos + while true # sequence + _text_start = self.pos + _tmp = apply(:_digit) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_country_code unless _tmp + return _tmp + end + + # area_code = < digit[3, 3] > { text } + def _area_code + + _save = self.pos + while true # sequence + _text_start = self.pos + _save1 = self.pos + _count = 0 + while true + _tmp = apply(:_digit) + if _tmp + _count += 1 + break if _count == 3 + else + break + end + end + if _count >= 3 + _tmp = true + else + self.pos = _save1 + _tmp = nil + end + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_area_code unless _tmp + return _tmp + end + + # prefix = < digit[3, 3] > { text } + def _prefix + + _save = self.pos + while true # sequence + _text_start = self.pos + _save1 = self.pos + _count = 0 + while true + _tmp = apply(:_digit) + if _tmp + _count += 1 + break if _count == 3 + else + break + end + end + if _count >= 3 + _tmp = true + else + self.pos = _save1 + _tmp = nil + end + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_prefix unless _tmp + return _tmp + end + + # suffix = < digit[4, 4] > { text } + def _suffix + + _save = self.pos + while true # sequence + _text_start = self.pos + _save1 = self.pos + _count = 0 + while true + _tmp = apply(:_digit) + if _tmp + _count += 1 + break if _count == 4 + else + break + end + end + if _count >= 4 + _tmp = true + else + self.pos = _save1 + _tmp = nil + end + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_suffix unless _tmp + return _tmp + end + + # phone_number = LP? area_code:ac RP? space* prefix:p space* dash? space* suffix:s space* { "(#{ac}) #{p}-#{s}" } + def _phone_number + + _save = self.pos + while true # sequence + _save1 = self.pos + _tmp = apply(:_LP) + unless _tmp + _tmp = true + self.pos = _save1 + end + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_area_code) + ac = @result + unless _tmp + self.pos = _save + break + end + _save2 = self.pos + _tmp = apply(:_RP) + unless _tmp + _tmp = true + self.pos = _save2 + end + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_prefix) + p = @result + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _save5 = self.pos + _tmp = apply(:_dash) + unless _tmp + _tmp = true + self.pos = _save5 + end + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_suffix) + s = @result + unless _tmp + self.pos = _save + break + end + while true + _tmp = apply(:_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save + break + end + @result = begin; "(#{ac}) #{p}-#{s}" ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_phone_number unless _tmp + return _tmp + end + + # root = (phone_number:pn { @phone_number = pn } | country_code:c space* phone_number:pn { @phone_number = "+#{c} #{pn}" }) + def _root + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_phone_number) + pn = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; @phone_number = pn ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = apply(:_country_code) + c = @result + unless _tmp + self.pos = _save2 + break + end + while true + _tmp = apply(:_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_phone_number) + pn = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; @phone_number = "+#{c} #{pn}" ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_root unless _tmp + return _tmp + end + + Rules = {} + Rules[:_digit] = rule_info("digit", "[0-9]") + Rules[:_space] = rule_info("space", "\" \"") + Rules[:_dash] = rule_info("dash", "\"-\"") + Rules[:_LP] = rule_info("LP", "\"(\"") + Rules[:_RP] = rule_info("RP", "\")\"") + Rules[:_country_code] = rule_info("country_code", "< digit > { text }") + Rules[:_area_code] = rule_info("area_code", "< digit[3, 3] > { text }") + Rules[:_prefix] = rule_info("prefix", "< digit[3, 3] > { text }") + Rules[:_suffix] = rule_info("suffix", "< digit[4, 4] > { text }") + Rules[:_phone_number] = rule_info("phone_number", "LP? area_code:ac RP? space* prefix:p space* dash? space* suffix:s space* { \"(\#{ac}) \#{p}-\#{s}\" }") + Rules[:_root] = rule_info("root", "(phone_number:pn { @phone_number = pn } | country_code:c space* phone_number:pn { @phone_number = \"+\#{c} \#{pn}\" })") + # :startdoc: +end diff --git a/examples/tiny_markdown/tiny_markdown.kpeg.rb b/examples/tiny_markdown/tiny_markdown.kpeg.rb index 66bdc58..010a3f3 100644 --- a/examples/tiny_markdown/tiny_markdown.kpeg.rb +++ b/examples/tiny_markdown/tiny_markdown.kpeg.rb @@ -18,6 +18,7 @@ def setup_parser(str, debug=false) @result = nil @failed_rule = nil @failing_rule_offset = -1 + @line_offsets = nil setup_foreign_grammar end @@ -27,30 +28,75 @@ def setup_parser(str, debug=false) attr_accessor :result, :pos def current_column(target=pos) - if c = string.rindex("\n", target-1) - return target - c - 1 + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c end target + 1 end - def current_line(target=pos) - cur_offset = 0 - cur_line = 0 + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end + + if [].respond_to? :bsearch_index + def current_line(target=pos) + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 + end + raise "Target position #{target} is outside of string" + end + else + def current_line(target=pos) + if line = position_line_offsets.index {|x| x > target } + return line + 1 + end - string.each_line do |line| - cur_line += 1 - cur_offset += line.size - return cur_line if cur_offset >= target + raise "Target position #{target} is outside of string" end + end - -1 + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) end def lines - lines = [] - string.each_line { |l| lines << l } - lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] end @@ -64,6 +110,7 @@ def set_string string, pos @string = string @string_size = string ? string.size : 0 @pos = pos + @position_line_offsets = nil end def show_pos @@ -88,30 +135,22 @@ def failure_info end def failure_caret - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - line = lines[l-1] - "#{line}\n#{' ' * (c - 1)}^" + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" end def failure_character - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - lines[l-1][c-1, 1] + current_character @failing_rule_offset end def failure_oneline - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - char = lines[l-1][c-1, 1] + p = current_pos_info @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] - "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" else - "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" end end @@ -124,10 +163,9 @@ def raise_error def show_error(io=STDOUT) error_pos = @failing_rule_offset - line_no = current_line(error_pos) - col_no = current_column(error_pos) + p = current_pos_info(error_pos) - io.puts "On line #{line_no}, column #{col_no}:" + io.puts "On line #{p.lno}, column #{p.col}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] @@ -136,10 +174,9 @@ def show_error(io=STDOUT) io.puts "Failed to match rule '#{@failed_rule}'" end - io.puts "Got: #{string[error_pos,1].inspect}" - line = lines[line_no-1] - io.puts "=> #{line}" - io.print(" " * (col_no + 3)) + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) io.puts "^" end @@ -163,9 +200,8 @@ def match_string(str) end def scan(reg) - if m = reg.match(@string[@pos..-1]) - width = m.end(0) - @pos += width + if m = reg.match(@string, @pos) + @pos = m.end(0) return true end @@ -249,6 +285,7 @@ def external_invoke(other, rule, *args) end def apply_with_args(rule, *args) + @result = nil memo_key = [rule, args] if m = @memoizations[memo_key][@pos] @pos = m.pos @@ -278,12 +315,11 @@ def apply_with_args(rule, *args) else return ans end - - return ans end end def apply(rule) + @result = nil if m = @memoizations[rule][@pos] @pos = m.pos if !m.set @@ -312,8 +348,6 @@ def apply(rule) else return ans end - - return ans end end @@ -808,7 +842,7 @@ def _AtxStart _save = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix:######|#####|####|###|##|#)/) + _tmp = scan(/\G(?-mix:######|#####|####|###|##|#)/) if _tmp text = get_text(_text_start) end @@ -2941,7 +2975,7 @@ def _Ticks1 _save = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix:`)/) + _tmp = scan(/\G(?-mix:`)/) if _tmp text = get_text(_text_start) end @@ -2975,7 +3009,7 @@ def _Ticks2 _save = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix:``)/) + _tmp = scan(/\G(?-mix:``)/) if _tmp text = get_text(_text_start) end @@ -3340,7 +3374,7 @@ def _Spacechar _save = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix: |\t)/) + _tmp = scan(/\G(?-mix: |\t)/) if _tmp text = get_text(_text_start) end @@ -3496,7 +3530,7 @@ def _SpecialChar _save = self.pos while true # sequence _text_start = self.pos - _tmp = scan(/\A(?-mix:[~*_`&\[\]() target } + return line + 1 + end + raise "Target position #{target} is outside of string" + end + else + def current_line(target=pos) + if line = position_line_offsets.index {|x| x > target } + return line + 1 + end + + raise "Target position #{target} is outside of string" + end + end + + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) + end + + def lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] + end + + + + def get_text(start) + @string[start..@pos-1] + end + + # Sets the string and current parsing position for the parser. + def set_string string, pos + @string = string + @string_size = string ? string.size : 0 + @pos = pos + @position_line_offsets = nil + end + + def show_pos + width = 10 + if @pos < width + "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" + else + "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" + end + end + + def failure_info + l = current_line @failing_rule_offset + c = current_column @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" + else + "line #{l}, column #{c}: failed rule '#{@failed_rule}'" + end + end + + def failure_caret + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" + end + + def failure_character + current_character @failing_rule_offset + end + + def failure_oneline + p = current_pos_info @failing_rule_offset + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" + else + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" + end + end + + class ParseError < RuntimeError + end + + def raise_error + raise ParseError, failure_oneline + end + + def show_error(io=STDOUT) + error_pos = @failing_rule_offset + p = current_pos_info(error_pos) + + io.puts "On line #{p.lno}, column #{p.col}:" + + if @failed_rule.kind_of? Symbol + info = self.class::Rules[@failed_rule] + io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" + else + io.puts "Failed to match rule '#{@failed_rule}'" + end + + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) + io.puts "^" + end + + def set_failed_rule(name) + if @pos > @failing_rule_offset + @failed_rule = name + @failing_rule_offset = @pos + end + end + + attr_reader :failed_rule + + def match_string(str) + len = str.size + if @string[pos,len] == str + @pos += len + return str + end + + return nil + end + + def scan(reg) + if m = reg.match(@string, @pos) + @pos = m.end(0) + return true + end + + return nil + end + + if "".respond_to? :ord + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos].ord + @pos += 1 + s + end + else + def get_byte + if @pos >= @string_size + return nil + end + + s = @string[@pos] + @pos += 1 + s + end + end + + def parse(rule=nil) + # We invoke the rules indirectly via apply + # instead of by just calling them as methods because + # if the rules use left recursion, apply needs to + # manage that. + + if !rule + apply(:_root) + else + method = rule.gsub("-","_hyphen_") + apply :"_#{method}" + end + end + + class MemoEntry + def initialize(ans, pos) + @ans = ans + @pos = pos + @result = nil + @set = false + @left_rec = false + end + + attr_reader :ans, :pos, :result, :set + attr_accessor :left_rec + + def move!(ans, pos, result) + @ans = ans + @pos = pos + @result = result + @set = true + @left_rec = false + end + end + + def external_invoke(other, rule, *args) + old_pos = @pos + old_string = @string + + set_string other.string, other.pos + + begin + if val = __send__(rule, *args) + other.pos = @pos + other.result = @result + else + other.set_failed_rule "#{self.class}##{rule}" + end + val + ensure + set_string old_string, old_pos + end + end + + def apply_with_args(rule, *args) + @result = nil + memo_key = [rule, args] + if m = @memoizations[memo_key][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[memo_key][@pos] = m + start_pos = @pos + + ans = __send__ rule, *args + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, args, start_pos, m) + else + return ans + end + end + end + + def apply(rule) + @result = nil + if m = @memoizations[rule][@pos] + @pos = m.pos + if !m.set + m.left_rec = true + return nil + end + + @result = m.result + + return m.ans + else + m = MemoEntry.new(nil, @pos) + @memoizations[rule][@pos] = m + start_pos = @pos + + ans = __send__ rule + + lr = m.left_rec + + m.move! ans, @pos, @result + + # Don't bother trying to grow the left recursion + # if it's failing straight away (thus there is no seed) + if ans and lr + return grow_lr(rule, nil, start_pos, m) + else + return ans + end + end + end + + def grow_lr(rule, args, start_pos, m) + while true + @pos = start_pos + @result = m.result + + if args + ans = __send__ rule, *args + else + ans = __send__ rule + end + return nil unless ans + + break if @pos <= m.pos + + m.move! ans, @pos, @result + end + + @result = m.result + @pos = m.pos + return m.ans + end + + class RuleInfo + def initialize(name, rendered) + @name = name + @rendered = rendered + end + + attr_reader :name, :rendered + end + + def self.rule_info(name, rendered) + RuleInfo.new(name, rendered) + end + + + # :startdoc: + + + attr_accessor :output + + + # :stopdoc: + def setup_foreign_grammar; end + + # period = "." + def _period + _tmp = match_string(".") + set_failed_rule :_period unless _tmp + return _tmp + end + + # space = " " + def _space + _tmp = match_string(" ") + set_failed_rule :_space unless _tmp + return _tmp + end + + # alpha = < /[A-Za-z]/ > { text.upcase } + def _alpha + + _save = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\G(?-mix:[A-Za-z])/) + if _tmp + text = get_text(_text_start) + end + unless _tmp + self.pos = _save + break + end + @result = begin; text.upcase ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_alpha unless _tmp + return _tmp + end + + # word = (alpha:a word:w { "#{a}#{w}" } | alpha:a space { "#{a} "} | alpha:a { a }) + def _word + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_alpha) + a = @result + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_word) + w = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; "#{a}#{w}" ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = apply(:_alpha) + a = @result + unless _tmp + self.pos = _save2 + break + end + _tmp = apply(:_space) + unless _tmp + self.pos = _save2 + break + end + @result = begin; "#{a} "; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save3 = self.pos + while true # sequence + _tmp = apply(:_alpha) + a = @result + unless _tmp + self.pos = _save3 + break + end + @result = begin; a ; end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_word unless _tmp + return _tmp + end + + # sentence = (word:w sentence:s { "#{w}#{s}" } | word:w { w }) + def _sentence + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_word) + w = @result + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_sentence) + s = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; "#{w}#{s}" ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save2 = self.pos + while true # sequence + _tmp = apply(:_word) + w = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; w ; end + _tmp = true + unless _tmp + self.pos = _save2 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_sentence unless _tmp + return _tmp + end + + # document = (sentence:s period space* document:d { "#{s}. #{d}" } | sentence:s period { "#{s}." } | sentence:s { "#{s}" }) + def _document + + _save = self.pos + while true # choice + + _save1 = self.pos + while true # sequence + _tmp = apply(:_sentence) + s = @result + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_period) + unless _tmp + self.pos = _save1 + break + end + while true + _tmp = apply(:_space) + break unless _tmp + end + _tmp = true + unless _tmp + self.pos = _save1 + break + end + _tmp = apply(:_document) + d = @result + unless _tmp + self.pos = _save1 + break + end + @result = begin; "#{s}. #{d}" ; end + _tmp = true + unless _tmp + self.pos = _save1 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save3 = self.pos + while true # sequence + _tmp = apply(:_sentence) + s = @result + unless _tmp + self.pos = _save3 + break + end + _tmp = apply(:_period) + unless _tmp + self.pos = _save3 + break + end + @result = begin; "#{s}." ; end + _tmp = true + unless _tmp + self.pos = _save3 + end + break + end # end sequence + + break if _tmp + self.pos = _save + + _save4 = self.pos + while true # sequence + _tmp = apply(:_sentence) + s = @result + unless _tmp + self.pos = _save4 + break + end + @result = begin; "#{s}" ; end + _tmp = true + unless _tmp + self.pos = _save4 + end + break + end # end sequence + + break if _tmp + self.pos = _save + break + end # end choice + + set_failed_rule :_document unless _tmp + return _tmp + end + + # root = document:d { @output = d } + def _root + + _save = self.pos + while true # sequence + _tmp = apply(:_document) + d = @result + unless _tmp + self.pos = _save + break + end + @result = begin; @output = d ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_root unless _tmp + return _tmp + end + + Rules = {} + Rules[:_period] = rule_info("period", "\".\"") + Rules[:_space] = rule_info("space", "\" \"") + Rules[:_alpha] = rule_info("alpha", "< /[A-Za-z]/ > { text.upcase }") + Rules[:_word] = rule_info("word", "(alpha:a word:w { \"\#{a}\#{w}\" } | alpha:a space { \"\#{a} \"} | alpha:a { a })") + Rules[:_sentence] = rule_info("sentence", "(word:w sentence:s { \"\#{w}\#{s}\" } | word:w { w })") + Rules[:_document] = rule_info("document", "(sentence:s period space* document:d { \"\#{s}. \#{d}\" } | sentence:s period { \"\#{s}.\" } | sentence:s { \"\#{s}\" })") + Rules[:_root] = rule_info("root", "document:d { @output = d }") + # :startdoc: +end From 946f47c1af193e65eb78b2668386ae7665372770 Mon Sep 17 00:00:00 2001 From: Yura Sokolov Date: Sun, 13 Aug 2023 04:37:01 +0300 Subject: [PATCH 2/3] Allow position to target just at string end (past last char) tiny_markdown example fails otherwise. It were broken with mine cf8f511 "add more tests to position handling and fix them" --- examples/calculator/calculator.kpeg.rb | 14 +++++++++--- examples/foreign_reference/literals.kpeg.rb | 14 +++++++++--- examples/foreign_reference/matcher.kpeg.rb | 14 +++++++++--- examples/lua_string/lua_string.kpeg.rb | 14 +++++++++--- examples/phone_number/phone_number.kpeg.rb | 14 +++++++++--- examples/tiny_markdown/tiny_markdown.kpeg.rb | 14 +++++++++--- examples/upper/upper.kpeg.rb | 14 +++++++++--- lib/kpeg/format_parser.rb | 14 +++++++++--- lib/kpeg/position.rb | 14 +++++++++--- lib/kpeg/string_escape.rb | 14 +++++++++--- test/test_kpeg_compiled_parser.rb | 24 ++++++++++++++++++++ 11 files changed, 134 insertions(+), 30 deletions(-) diff --git a/examples/calculator/calculator.kpeg.rb b/examples/calculator/calculator.kpeg.rb index 0af26ee..3010172 100644 --- a/examples/calculator/calculator.kpeg.rb +++ b/examples/calculator/calculator.kpeg.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/examples/foreign_reference/literals.kpeg.rb b/examples/foreign_reference/literals.kpeg.rb index 4ebdbff..5afa2b7 100644 --- a/examples/foreign_reference/literals.kpeg.rb +++ b/examples/foreign_reference/literals.kpeg.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/examples/foreign_reference/matcher.kpeg.rb b/examples/foreign_reference/matcher.kpeg.rb index 7e308ee..fbdab3f 100644 --- a/examples/foreign_reference/matcher.kpeg.rb +++ b/examples/foreign_reference/matcher.kpeg.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/examples/lua_string/lua_string.kpeg.rb b/examples/lua_string/lua_string.kpeg.rb index 42cf1fd..c7d5f4d 100644 --- a/examples/lua_string/lua_string.kpeg.rb +++ b/examples/lua_string/lua_string.kpeg.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/examples/phone_number/phone_number.kpeg.rb b/examples/phone_number/phone_number.kpeg.rb index 1a47588..53beb81 100644 --- a/examples/phone_number/phone_number.kpeg.rb +++ b/examples/phone_number/phone_number.kpeg.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/examples/tiny_markdown/tiny_markdown.kpeg.rb b/examples/tiny_markdown/tiny_markdown.kpeg.rb index 010a3f3..412a3e2 100644 --- a/examples/tiny_markdown/tiny_markdown.kpeg.rb +++ b/examples/tiny_markdown/tiny_markdown.kpeg.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/examples/upper/upper.kpeg.rb b/examples/upper/upper.kpeg.rb index 355f1d7..27816b6 100644 --- a/examples/upper/upper.kpeg.rb +++ b/examples/upper/upper.kpeg.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/lib/kpeg/format_parser.rb b/lib/kpeg/format_parser.rb index a66c5e6..c9aa51d 100644 --- a/lib/kpeg/format_parser.rb +++ b/lib/kpeg/format_parser.rb @@ -45,6 +45,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -52,17 +55,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/lib/kpeg/position.rb b/lib/kpeg/position.rb index cbb4fb4..8903096 100644 --- a/lib/kpeg/position.rb +++ b/lib/kpeg/position.rb @@ -28,6 +28,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -35,17 +38,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/lib/kpeg/string_escape.rb b/lib/kpeg/string_escape.rb index d433767..31f34fc 100644 --- a/lib/kpeg/string_escape.rb +++ b/lib/kpeg/string_escape.rb @@ -53,6 +53,9 @@ def position_line_offsets def current_line(target=pos) if line = position_line_offsets.bsearch_index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end raise "Target position #{target} is outside of string" end @@ -60,17 +63,22 @@ def current_line(target=pos) def current_line(target=pos) if line = position_line_offsets.index {|x| x > target } return line + 1 + elsif target == string.size + past_last = !string.empty? && string[-1]=="\n" ? 1 : 0 + return position_line_offsets.size + past_last end - raise "Target position #{target} is outside of string" end end def current_character(target=pos) - if target < 0 || target >= string.size + if target < 0 || target > string.size raise "Target position #{target} is outside of string" + elsif target == string.size + "" + else + string[target, 1] end - string[target, 1] end KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) diff --git a/test/test_kpeg_compiled_parser.rb b/test/test_kpeg_compiled_parser.rb index e9f6cf2..90d6e07 100644 --- a/test/test_kpeg_compiled_parser.rb +++ b/test/test_kpeg_compiled_parser.rb @@ -29,6 +29,12 @@ class TestKPegCompiledParser < Minitest::Test KPeg.compile gram, "ProdTestParser", self + gram = <<-GRAM + root = [a-z] "\n" + GRAM + + KPeg.compile gram, "TestNLParser", self + def test_current_column r = TestParser.new "hello\nsir\nand goodbye" assert_equal 1, r.current_column(0) @@ -104,6 +110,24 @@ def test_failure_oneline assert_equal expected, r.failure_oneline end + def test_position_at_the_end + r = TestParser.new "l" + assert r.parse, "should parse" + + assert_equal 1, r.pos + assert_equal 1, r.current_line + assert_equal 2, r.current_column + end + + def test_position_at_the_end_after_nl + r = TestNLParser.new "l\n" + assert r.parse, "should parse" + + assert_equal 2, r.pos + assert_equal 2, r.current_line + assert_equal 1, r.current_column + end + def test_composite_grammar r = CompTestParser.new "l!" assert r.parse, "should parse" From 0c3d2fdecaac9b920b5041b18a0e3366253af247 Mon Sep 17 00:00:00 2001 From: Yura Sokolov Date: Sun, 13 Aug 2023 18:06:35 +0300 Subject: [PATCH 3/3] Simplify generated code - rename `get_byte`->`match_dot`, add `match_char_range` - abuse choice variants reset position by themself - abuse optional rule reset position by itself - simplify sequence with resetting position after block instead of after each element - unify `+` and numbered repetition - strip actions body Also fix issue with nested repetition collection: - names `_ary` and `_count` were erroneously reused --- examples/calculator/calculator.kpeg.rb | 231 +- examples/foreign_reference/literals.kpeg.rb | 23 +- examples/foreign_reference/matcher.kpeg.rb | 95 +- examples/lua_string/lua_string.kpeg.rb | 135 +- examples/phone_number/phone_number.kpeg.rb | 310 +- examples/tiny_markdown/tiny_markdown.kpeg.rb | 3072 ++++++------------ examples/upper/upper.kpeg.rb | 267 +- lib/kpeg/code_generator.rb | 160 +- lib/kpeg/compiled_parser.rb | 23 +- lib/kpeg/format_parser.rb | 2478 +++++--------- lib/kpeg/string_escape.rb | 255 +- test/test_kpeg_code_generator.rb | 278 +- 12 files changed, 2468 insertions(+), 4859 deletions(-) diff --git a/examples/calculator/calculator.kpeg.rb b/examples/calculator/calculator.kpeg.rb index 3010172..4ca10cc 100644 --- a/examples/calculator/calculator.kpeg.rb +++ b/examples/calculator/calculator.kpeg.rb @@ -197,6 +197,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -413,11 +424,11 @@ def _space # - = space* def __hyphen_ - while true + while true # kleene _tmp = apply(:_space) break unless _tmp end - _tmp = true + _tmp = true # end kleene set_failed_rule :__hyphen_ unless _tmp return _tmp end @@ -426,22 +437,18 @@ def __hyphen_ def _num _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[1-9][0-9]*)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text.to_i ; end + break unless _tmp + @result = begin; text.to_i; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_num unless _tmp @@ -451,93 +458,55 @@ def _num # term = (term:t1 - "+" - term:t2 { t1 + t2 } | term:t1 - "-" - term:t2 { t1 - t2 } | fact) def _term - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_term) t1 = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string("+") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_term) t2 = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; t1 + t2 ; end + break unless _tmp + @result = begin; t1 + t2; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_term) t1 = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = match_string("-") - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_term) t2 = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; t1 - t2 ; end + break unless _tmp + @result = begin; t1 - t2; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_fact) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_term unless _tmp return _tmp @@ -546,93 +515,55 @@ def _term # fact = (fact:f1 - "*" - fact:f2 { f1 * f2 } | fact:f1 - "/" - fact:f2 { f1 / f2 } | num) def _fact - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_fact) f1 = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string("*") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_fact) f2 = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; f1 * f2 ; end + break unless _tmp + @result = begin; f1 * f2; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_fact) f1 = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = match_string("/") - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_fact) f2 = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; f1 / f2 ; end + break unless _tmp + @result = begin; f1 / f2; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_num) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_fact unless _tmp return _tmp @@ -642,19 +573,15 @@ def _fact def _root _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_term) t = @result - unless _tmp - self.pos = _save - break - end - @result = begin; @result = t ; end + break unless _tmp + @result = begin; @result = t; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp diff --git a/examples/foreign_reference/literals.kpeg.rb b/examples/foreign_reference/literals.kpeg.rb index 5afa2b7..7f6b227 100644 --- a/examples/foreign_reference/literals.kpeg.rb +++ b/examples/foreign_reference/literals.kpeg.rb @@ -197,6 +197,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end diff --git a/examples/foreign_reference/matcher.kpeg.rb b/examples/foreign_reference/matcher.kpeg.rb index fbdab3f..4c12355 100644 --- a/examples/foreign_reference/matcher.kpeg.rb +++ b/examples/foreign_reference/matcher.kpeg.rb @@ -197,6 +197,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -410,63 +421,37 @@ def setup_foreign_grammar def _root _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition + _count = 0 + while true - _save2 = self.pos - while true # sequence - _tmp = @_grammar_grammer1.external_invoke(self, :_alpha) - unless _tmp - self.pos = _save2 - break - end - while true - _tmp = @_grammar_grammer1.external_invoke(self, :_space) + _save2 = self.pos + begin # sequence + _tmp = @_grammar_grammer1.external_invoke(self, :_alpha) break unless _tmp - end - _tmp = true + while true # kleene + _tmp = @_grammar_grammer1.external_invoke(self, :_space) + break unless _tmp + end + _tmp = true # end kleene + end while false unless _tmp self.pos = _save2 - end - break - end # end sequence - - if _tmp - while true - - _save4 = self.pos - while true # sequence - _tmp = @_grammar_grammer1.external_invoke(self, :_alpha) - unless _tmp - self.pos = _save4 - break - end - while true - _tmp = @_grammar_grammer1.external_invoke(self, :_space) - break unless _tmp - end - _tmp = true - unless _tmp - self.pos = _save4 - end - break - end # end sequence + end # end sequence - break unless _tmp - end - _tmp = true - else - self.pos = _save1 + break unless _tmp + _count += 1 end + _tmp = _count >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save1 + end # end repetition + break unless _tmp _tmp = @_grammar_grammer1.external_invoke(self, :_period) - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp diff --git a/examples/lua_string/lua_string.kpeg.rb b/examples/lua_string/lua_string.kpeg.rb index c7d5f4d..c22f9d0 100644 --- a/examples/lua_string/lua_string.kpeg.rb +++ b/examples/lua_string/lua_string.kpeg.rb @@ -197,6 +197,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -408,26 +419,22 @@ def setup_foreign_grammar; end def _equals _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - while true + while true # kleene _tmp = match_string("=") break unless _tmp end - _tmp = true + _tmp = true # end kleene if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_equals unless _tmp @@ -438,30 +445,20 @@ def _equals def _equal_ending(start) _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("]") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_equals) x = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos - _tmp = begin; x == start ; end + _tmp = begin; x == start; end self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("]") - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_equal_ending unless _tmp @@ -472,66 +469,44 @@ def _equal_ending(start) def _root _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("[") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_equals) e = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("[") - unless _tmp - self.pos = _save - break - end + break unless _tmp _text_start = self.pos - while true + while true # kleene - _save2 = self.pos - while true # sequence - _save3 = self.pos + _save1 = self.pos + begin # sequence + _save2 = self.pos _tmp = apply_with_args(:_equal_ending, e) - _tmp = _tmp ? nil : true - self.pos = _save3 - unless _tmp - self.pos = _save2 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save2 - end - break + _tmp = !_tmp + self.pos = _save2 + break unless _tmp + _tmp = match_dot + end while false + unless _tmp + self.pos = _save1 end # end sequence break unless _tmp end - _tmp = true + _tmp = true # end kleene if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply_with_args(:_equal_ending, e) - unless _tmp - self.pos = _save - break - end - @result = begin; - @result = text - ; end + break unless _tmp + @result = begin; @result = text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp diff --git a/examples/phone_number/phone_number.kpeg.rb b/examples/phone_number/phone_number.kpeg.rb index 53beb81..ff42c63 100644 --- a/examples/phone_number/phone_number.kpeg.rb +++ b/examples/phone_number/phone_number.kpeg.rb @@ -197,6 +197,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -406,14 +417,7 @@ def setup_foreign_grammar; end # digit = [0-9] def _digit - _save = self.pos - _tmp = get_byte - if _tmp - unless _tmp >= 48 and _tmp <= 57 - self.pos = _save - _tmp = nil - end - end + _tmp = match_char_range(48..57) set_failed_rule :_digit unless _tmp return _tmp end @@ -450,22 +454,18 @@ def _RP def _country_code _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = apply(:_digit) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_country_code unless _tmp @@ -476,38 +476,29 @@ def _country_code def _area_code _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - _save1 = self.pos + _save1 = self.pos # repetition _count = 0 while true _tmp = apply(:_digit) - if _tmp - _count += 1 - break if _count == 3 - else - break - end + break unless _tmp + _count += 1 + break if _count == 3 end - if _count >= 3 - _tmp = true - else + _tmp = _count >= 3 + unless _tmp self.pos = _save1 - _tmp = nil - end + end # end repetition if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_area_code unless _tmp @@ -518,38 +509,29 @@ def _area_code def _prefix _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - _save1 = self.pos + _save1 = self.pos # repetition _count = 0 while true _tmp = apply(:_digit) - if _tmp - _count += 1 - break if _count == 3 - else - break - end + break unless _tmp + _count += 1 + break if _count == 3 end - if _count >= 3 - _tmp = true - else + _tmp = _count >= 3 + unless _tmp self.pos = _save1 - _tmp = nil - end + end # end repetition if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_prefix unless _tmp @@ -560,38 +542,29 @@ def _prefix def _suffix _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - _save1 = self.pos + _save1 = self.pos # repetition _count = 0 while true _tmp = apply(:_digit) - if _tmp - _count += 1 - break if _count == 4 - else - break - end + break unless _tmp + _count += 1 + break if _count == 4 end - if _count >= 4 - _tmp = true - else + _tmp = _count >= 4 + unless _tmp self.pos = _save1 - _tmp = nil - end + end # end repetition if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_suffix unless _tmp @@ -602,97 +575,57 @@ def _suffix def _phone_number _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + # optional _tmp = apply(:_LP) - unless _tmp - _tmp = true - self.pos = _save1 - end - unless _tmp - self.pos = _save - break - end + _tmp = true # end optional + break unless _tmp _tmp = apply(:_area_code) ac = @result - unless _tmp - self.pos = _save - break - end - _save2 = self.pos + break unless _tmp + # optional _tmp = apply(:_RP) - unless _tmp - _tmp = true - self.pos = _save2 - end - unless _tmp - self.pos = _save - break - end - while true + _tmp = true # end optional + break unless _tmp + while true # kleene _tmp = apply(:_space) break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - break - end + _tmp = true # end kleene + break unless _tmp _tmp = apply(:_prefix) p = @result - unless _tmp - self.pos = _save - break - end - while true + break unless _tmp + while true # kleene _tmp = apply(:_space) break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - break - end - _save5 = self.pos + _tmp = true # end kleene + break unless _tmp + # optional _tmp = apply(:_dash) - unless _tmp - _tmp = true - self.pos = _save5 - end - unless _tmp - self.pos = _save - break - end - while true + _tmp = true # end optional + break unless _tmp + while true # kleene _tmp = apply(:_space) break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - break - end + _tmp = true # end kleene + break unless _tmp _tmp = apply(:_suffix) s = @result - unless _tmp - self.pos = _save - break - end - while true + break unless _tmp + while true # kleene _tmp = apply(:_space) break unless _tmp end + _tmp = true # end kleene + break unless _tmp + @result = begin; "(#{ac}) #{p}-#{s}"; end _tmp = true - unless _tmp - self.pos = _save - break - end - @result = begin; "(#{ac}) #{p}-#{s}" ; end - _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_phone_number unless _tmp @@ -702,63 +635,44 @@ def _phone_number # root = (phone_number:pn { @phone_number = pn } | country_code:c space* phone_number:pn { @phone_number = "+#{c} #{pn}" }) def _root - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_phone_number) pn = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; @phone_number = pn ; end + break unless _tmp + @result = begin; @phone_number = pn; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_country_code) c = @result - unless _tmp - self.pos = _save2 - break - end - while true + break unless _tmp + while true # kleene _tmp = apply(:_space) break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save2 - break - end + _tmp = true # end kleene + break unless _tmp _tmp = apply(:_phone_number) pn = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; @phone_number = "+#{c} #{pn}" ; end + break unless _tmp + @result = begin; @phone_number = "+#{c} #{pn}"; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_root unless _tmp return _tmp diff --git a/examples/tiny_markdown/tiny_markdown.kpeg.rb b/examples/tiny_markdown/tiny_markdown.kpeg.rb index 412a3e2..bac5945 100644 --- a/examples/tiny_markdown/tiny_markdown.kpeg.rb +++ b/examples/tiny_markdown/tiny_markdown.kpeg.rb @@ -197,6 +197,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -604,26 +615,19 @@ def _root def _Start _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos - _tmp = get_byte + _tmp = match_dot self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Doc) c = @result - unless _tmp - self.pos = _save - break - end - @result = begin; @ast = c ; end + break unless _tmp + @result = begin; @ast = c; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Start unless _tmp @@ -634,26 +638,22 @@ def _Start def _Doc _save = self.pos - while true # sequence - _ary = [] + begin # sequence + _ary = [] # kleene while true _tmp = apply(:_Block) - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene c = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; document(self, position, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Doc unless _tmp @@ -664,47 +664,33 @@ def _Doc def _Block _save = self.pos - while true # sequence - while true + begin # sequence + while true # kleene _tmp = apply(:_BlankLine) break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - break - end + _tmp = true # end kleene + break unless _tmp - _save2 = self.pos - while true # choice + begin # choice _tmp = apply(:_BlockQuote) break if _tmp - self.pos = _save2 _tmp = apply(:_Verbatim) break if _tmp - self.pos = _save2 _tmp = apply(:_HorizontalRule) break if _tmp - self.pos = _save2 _tmp = apply(:_Heading) break if _tmp - self.pos = _save2 _tmp = apply(:_BulletList) break if _tmp - self.pos = _save2 _tmp = apply(:_Para) break if _tmp - self.pos = _save2 _tmp = apply(:_Plain) - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Block unless _tmp @@ -715,39 +701,29 @@ def _Block def _Para _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_NonindentSpace) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Inlines) a = @result - unless _tmp - self.pos = _save - break - end - _save1 = self.pos - _tmp = apply(:_BlankLine) - if _tmp - while true - _tmp = apply(:_BlankLine) - break unless _tmp - end - _tmp = true - else - self.pos = _save1 + break unless _tmp + _save1 = self.pos # repetition + _count = 0 + while true + _tmp = apply(:_BlankLine) + break unless _tmp + _count += 1 end + _tmp = _count >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save1 + end # end repetition + break unless _tmp @result = begin; para(self, position, a); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Para unless _tmp @@ -758,19 +734,15 @@ def _Para def _Plain _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Inlines) a = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; plain(self, position, a); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Plain unless _tmp @@ -781,63 +753,43 @@ def _Plain def _AtxInline _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos _tmp = apply(:_Newline) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _save2 = self.pos _save3 = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save3 - break - end - while true + break unless _tmp + while true # kleene _tmp = match_string("#") break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save3 - break - end + _tmp = true # end kleene + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = apply(:_Newline) - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save3 end # end sequence - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save2 - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Inline) c = @result - unless _tmp - self.pos = _save - break - end - @result = begin; c ; end + break unless _tmp + @result = begin; c; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_AtxInline unless _tmp @@ -848,22 +800,18 @@ def _AtxInline def _AtxStart _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:######|#####|####|###|##|#)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text.length ; end + break unless _tmp + @result = begin; text.length; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_AtxStart unless _tmp @@ -874,82 +822,54 @@ def _AtxStart def _AtxHeading _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_AtxStart) level = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save - break - end - _save1 = self.pos + break unless _tmp + _save1 = self.pos # repetition _ary = [] - _tmp = apply(:_AtxInline) - if _tmp + while true + _tmp = apply(:_AtxInline) + break unless _tmp _ary << @result - while true - _tmp = apply(:_AtxInline) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - c = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end - _save2 = self.pos + self.pos = _save1 + @result = nil + end # end repetition + c = @result + break unless _tmp + # optional - _save3 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save3 - break - end - while true + break unless _tmp + while true # kleene _tmp = match_string("#") break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save3 - break - end + _tmp = true # end kleene + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save3 - end - break - end # end sequence - + end while false unless _tmp - _tmp = true self.pos = _save2 - end - unless _tmp - self.pos = _save - break - end + end # end sequence + + _tmp = true # end optional + break unless _tmp _tmp = apply(:_Newline) - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; headline(self, position, level, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_AtxHeading unless _tmp @@ -967,19 +887,15 @@ def _Heading def _BlockQuote _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_BlockQuoteRaw) c = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; block_quote(self, position, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_BlockQuote unless _tmp @@ -990,95 +906,45 @@ def _BlockQuote def _BlockQuoteRaw _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] + while true - _save2 = self.pos - while true # sequence - _tmp = match_string(">") - unless _tmp - self.pos = _save2 - break - end - _save3 = self.pos - _tmp = match_string(" ") - unless _tmp + _save2 = self.pos + begin # sequence + _tmp = match_string(">") + break unless _tmp + # optional + _tmp = match_string(" ") + _tmp = true # end optional + break unless _tmp + _tmp = apply(:_Line) + c = @result + break unless _tmp + @result = begin; c; end _tmp = true - self.pos = _save3 - end - unless _tmp - self.pos = _save2 - break - end - _tmp = apply(:_Line) - c = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; c ; end - _tmp = true + end while false unless _tmp self.pos = _save2 - end - break - end # end sequence + end # end sequence - if _tmp + break unless _tmp _ary << @result - while true - - _save4 = self.pos - while true # sequence - _tmp = match_string(">") - unless _tmp - self.pos = _save4 - break - end - _save5 = self.pos - _tmp = match_string(" ") - unless _tmp - _tmp = true - self.pos = _save5 - end - unless _tmp - self.pos = _save4 - break - end - _tmp = apply(:_Line) - c = @result - unless _tmp - self.pos = _save4 - break - end - @result = begin; c ; end - _tmp = true - unless _tmp - self.pos = _save4 - end - break - end # end sequence - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - cc = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end - @result = begin; cc ; end + self.pos = _save1 + @result = nil + end # end repetition + cc = @result + break unless _tmp + @result = begin; cc; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_BlockQuoteRaw unless _tmp @@ -1089,27 +955,20 @@ def _BlockQuoteRaw def _NonblankIndentedLine _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos _tmp = apply(:_BlankLine) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_IndentedLine) c = @result - unless _tmp - self.pos = _save - break - end - @result = begin; c ; end + break unless _tmp + @result = begin; c; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_NonblankIndentedLine unless _tmp @@ -1120,93 +979,60 @@ def _NonblankIndentedLine def _VerbatimChunk _save = self.pos - while true # sequence - _ary = [] + begin # sequence + _ary = [] # kleene while true - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_BlankLine) - unless _tmp - self.pos = _save2 - break - end - @result = begin; text(self,position,"\n") ; end + break unless _tmp + @result = begin; text(self,position,"\n"); end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene c1 = @result - unless _tmp - self.pos = _save - break - end - _save3 = self.pos - _ary = [] + break unless _tmp + _save2 = self.pos # repetition + _ary1 = [] + while true - _save4 = self.pos - while true # sequence - _tmp = apply(:_NonblankIndentedLine) - c = @result - unless _tmp - self.pos = _save4 - break - end - @result = begin; [c, text(self,position,"\n")] ; end - _tmp = true + _save3 = self.pos + begin # sequence + _tmp = apply(:_NonblankIndentedLine) + c = @result + break unless _tmp + @result = begin; [c, text(self,position,"\n")]; end + _tmp = true + end while false unless _tmp - self.pos = _save4 - end - break - end # end sequence - - if _tmp - _ary << @result - while true - - _save5 = self.pos - while true # sequence - _tmp = apply(:_NonblankIndentedLine) - c = @result - unless _tmp - self.pos = _save5 - break - end - @result = begin; [c, text(self,position,"\n")] ; end - _tmp = true - unless _tmp - self.pos = _save5 - end - break - end # end sequence + self.pos = _save3 + end # end sequence - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save3 + break unless _tmp + _ary1 << @result end - c2 = @result + @result = _ary1 + _tmp = _ary1.size >= 1 unless _tmp - self.pos = _save - break - end - @result = begin; c1 + c2.flatten ; end + self.pos = _save2 + @result = nil + end # end repetition + c2 = @result + break unless _tmp + @result = begin; c1 + c2.flatten; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_VerbatimChunk unless _tmp @@ -1217,33 +1043,27 @@ def _VerbatimChunk def _Verbatim _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] - _tmp = apply(:_VerbatimChunk) - if _tmp + while true + _tmp = apply(:_VerbatimChunk) + break unless _tmp _ary << @result - while true - _tmp = apply(:_VerbatimChunk) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - cc = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save1 + @result = nil + end # end repetition + cc = @result + break unless _tmp @result = begin; verbatim(self, position, cc.flatten); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Verbatim unless _tmp @@ -1254,218 +1074,136 @@ def _Verbatim def _HorizontalRule _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_NonindentSpace) - unless _tmp - self.pos = _save - break - end + break unless _tmp - _save1 = self.pos - while true # choice + begin # choice - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = match_string("*") - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = match_string("*") - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = match_string("*") - unless _tmp - self.pos = _save2 - break - end - while true + break unless _tmp + while true # kleene - _save4 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save4 - break - end + break unless _tmp _tmp = match_string("*") - unless _tmp - self.pos = _save4 - end - break + end while false + unless _tmp + self.pos = _save2 end # end sequence break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save2 - end - break + _tmp = true # end kleene + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save1 - _save5 = self.pos - while true # sequence + _save3 = self.pos + begin # sequence _tmp = match_string("-") - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = match_string("-") - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = match_string("-") - unless _tmp - self.pos = _save5 - break - end - while true + break unless _tmp + while true # kleene - _save7 = self.pos - while true # sequence + _save4 = self.pos + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save7 - break - end + break unless _tmp _tmp = match_string("-") - unless _tmp - self.pos = _save7 - end - break + end while false + unless _tmp + self.pos = _save4 end # end sequence break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save5 - end - break + _tmp = true # end kleene + end while false + unless _tmp + self.pos = _save3 end # end sequence break if _tmp - self.pos = _save1 - _save8 = self.pos - while true # sequence + _save5 = self.pos + begin # sequence _tmp = match_string("_") - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = match_string("_") - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = match_string("_") - unless _tmp - self.pos = _save8 - break - end - while true + break unless _tmp + while true # kleene - _save10 = self.pos - while true # sequence + _save6 = self.pos + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save10 - break - end + break unless _tmp _tmp = match_string("_") - unless _tmp - self.pos = _save10 - end - break + end while false + unless _tmp + self.pos = _save6 end # end sequence break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save8 - end - break + _tmp = true # end kleene + end while false + unless _tmp + self.pos = _save5 end # end sequence - break if _tmp - self.pos = _save1 - break - end # end choice + end while false # end choice - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Newline) - unless _tmp - self.pos = _save - break - end - _save11 = self.pos - _tmp = apply(:_BlankLine) - if _tmp - while true - _tmp = apply(:_BlankLine) - break unless _tmp - end - _tmp = true - else - self.pos = _save11 + break unless _tmp + _save7 = self.pos # repetition + _count = 0 + while true + _tmp = apply(:_BlankLine) + break unless _tmp + _count += 1 end + _tmp = _count >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save7 + end # end repetition + break unless _tmp @result = begin; horizontal_rule(self, position); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_HorizontalRule unless _tmp @@ -1476,54 +1214,38 @@ def _HorizontalRule def _Bullet _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos _tmp = apply(:_HorizontalRule) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_NonindentSpace) - unless _tmp - self.pos = _save - break - end + break unless _tmp - _save2 = self.pos - while true # choice + begin # choice _tmp = match_string("+") break if _tmp - self.pos = _save2 _tmp = match_string("*") break if _tmp - self.pos = _save2 _tmp = match_string("-") - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice - unless _tmp - self.pos = _save - break - end - _save3 = self.pos - _tmp = apply(:_Spacechar) - if _tmp - while true - _tmp = apply(:_Spacechar) - break unless _tmp - end - _tmp = true - else - self.pos = _save3 + break unless _tmp + _save2 = self.pos # repetition + _count = 0 + while true + _tmp = apply(:_Spacechar) + break unless _tmp + _count += 1 end + _tmp = _count >= 1 unless _tmp - self.pos = _save - end - break + self.pos = _save2 + end # end repetition + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Bullet unless _tmp @@ -1534,26 +1256,19 @@ def _Bullet def _BulletList _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos _tmp = apply(:_Bullet) self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_ListTight) c = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; bullet_list(self, position, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_BulletList unless _tmp @@ -1564,50 +1279,38 @@ def _BulletList def _ListTight _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] - _tmp = apply(:_ListItemTight) - if _tmp + while true + _tmp = apply(:_ListItemTight) + break unless _tmp _ary << @result - while true - _tmp = apply(:_ListItemTight) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - cc = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end - while true + self.pos = _save1 + @result = nil + end # end repetition + cc = @result + break unless _tmp + while true # kleene _tmp = apply(:_BlankLine) break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - break - end - _save3 = self.pos + _tmp = true # end kleene + break unless _tmp + _save2 = self.pos _tmp = apply(:_Bullet) - _tmp = _tmp ? nil : true - self.pos = _save3 - unless _tmp - self.pos = _save - break - end - @result = begin; cc ; end + _tmp = !_tmp + self.pos = _save2 + break unless _tmp + @result = begin; cc; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_ListTight unless _tmp @@ -1618,24 +1321,17 @@ def _ListTight def _ListItemTight _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Bullet) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_ListBlock) c = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; bullet_list_item(self, position, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_ListItemTight unless _tmp @@ -1646,40 +1342,30 @@ def _ListItemTight def _ListBlock _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos _tmp = apply(:_BlankLine) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Line) c = @result - unless _tmp - self.pos = _save - break - end - _ary = [] + break unless _tmp + _ary = [] # kleene while true _tmp = apply(:_ListBlockLine) - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene cc = @result - unless _tmp - self.pos = _save - break - end - @result = begin; cc.unshift(c) ; end + break unless _tmp + @result = begin; cc.unshift(c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_ListBlock unless _tmp @@ -1690,55 +1376,38 @@ def _ListBlock def _ListBlockLine _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos _tmp = apply(:_BlankLine) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _save2 = self.pos _save3 = self.pos - while true # sequence - _save4 = self.pos + begin # sequence + # optional _tmp = apply(:_Indent) - unless _tmp - _tmp = true - self.pos = _save4 - end - unless _tmp - self.pos = _save3 - break - end + _tmp = true # end optional + break unless _tmp _tmp = apply(:_Bullet) - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save3 end # end sequence - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save2 - unless _tmp - self.pos = _save - break - end - _save5 = self.pos + break unless _tmp + _save4 = self.pos _tmp = apply(:_HorizontalRule) - _tmp = _tmp ? nil : true - self.pos = _save5 - unless _tmp - self.pos = _save - break - end + _tmp = !_tmp + self.pos = _save4 + break unless _tmp _tmp = apply(:_OptionallyIndentedLine) - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_ListBlockLine unless _tmp @@ -1749,159 +1418,70 @@ def _ListBlockLine def _Inlines _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] + while true - _save2 = self.pos - while true # choice + begin # choice - _save3 = self.pos - while true # sequence - _save4 = self.pos - _tmp = apply(:_Endline) - _tmp = _tmp ? nil : true - self.pos = _save4 - unless _tmp - self.pos = _save3 - break - end - _tmp = apply(:_Inline) - c = @result - unless _tmp + _save2 = self.pos + begin # sequence + _save3 = self.pos + _tmp = apply(:_Endline) + _tmp = !_tmp self.pos = _save3 - break - end - @result = begin; c ; end - _tmp = true + break unless _tmp + _tmp = apply(:_Inline) + c = @result + break unless _tmp + @result = begin; c; end + _tmp = true + end while false unless _tmp - self.pos = _save3 - end - break - end # end sequence + self.pos = _save2 + end # end sequence - break if _tmp - self.pos = _save2 + break if _tmp - _save5 = self.pos - while true # sequence - _tmp = apply(:_Endline) - c = @result - unless _tmp - self.pos = _save5 - break - end - _save6 = self.pos - _tmp = apply(:_Inline) - self.pos = _save6 - unless _tmp + _save4 = self.pos + begin # sequence + _tmp = apply(:_Endline) + c = @result + break unless _tmp + _save5 = self.pos + _tmp = apply(:_Inline) self.pos = _save5 - break - end - @result = begin; c ; end - _tmp = true + break unless _tmp + @result = begin; c; end + _tmp = true + end while false unless _tmp - self.pos = _save5 - end - break - end # end sequence + self.pos = _save4 + end # end sequence - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice - if _tmp + break unless _tmp _ary << @result - while true - - _save7 = self.pos - while true # choice - - _save8 = self.pos - while true # sequence - _save9 = self.pos - _tmp = apply(:_Endline) - _tmp = _tmp ? nil : true - self.pos = _save9 - unless _tmp - self.pos = _save8 - break - end - _tmp = apply(:_Inline) - c = @result - unless _tmp - self.pos = _save8 - break - end - @result = begin; c ; end - _tmp = true - unless _tmp - self.pos = _save8 - end - break - end # end sequence - - break if _tmp - self.pos = _save7 - - _save10 = self.pos - while true # sequence - _tmp = apply(:_Endline) - c = @result - unless _tmp - self.pos = _save10 - break - end - _save11 = self.pos - _tmp = apply(:_Inline) - self.pos = _save11 - unless _tmp - self.pos = _save10 - break - end - @result = begin; c ; end - _tmp = true - unless _tmp - self.pos = _save10 - end - break - end # end sequence - - break if _tmp - self.pos = _save7 - break - end # end choice - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - cc = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end - _save12 = self.pos + self.pos = _save1 + @result = nil + end # end repetition + cc = @result + break unless _tmp + # optional _tmp = apply(:_Endline) - unless _tmp - _tmp = true - self.pos = _save12 - end - unless _tmp - self.pos = _save - break - end - @result = begin; cc ; end + _tmp = true # end optional + break unless _tmp + @result = begin; cc; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Inlines unless _tmp @@ -1911,31 +1491,21 @@ def _Inlines # Inline = (Str | Endline | Space | Strong | Emph | Code | Symbol) def _Inline - _save = self.pos - while true # choice + begin # choice _tmp = apply(:_Str) break if _tmp - self.pos = _save _tmp = apply(:_Endline) break if _tmp - self.pos = _save _tmp = apply(:_Space) break if _tmp - self.pos = _save _tmp = apply(:_Strong) break if _tmp - self.pos = _save _tmp = apply(:_Emph) break if _tmp - self.pos = _save _tmp = apply(:_Code) break if _tmp - self.pos = _save _tmp = apply(:_Symbol) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_Inline unless _tmp return _tmp @@ -1945,33 +1515,27 @@ def _Inline def _Space _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] - _tmp = apply(:_Spacechar) - if _tmp + while true + _tmp = apply(:_Spacechar) + break unless _tmp _ary << @result - while true - _tmp = apply(:_Spacechar) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - c = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save1 + @result = nil + end # end repetition + c = @result + break unless _tmp @result = begin; text(self, position, c.join("")); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Space unless _tmp @@ -1982,46 +1546,37 @@ def _Space def _Str _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] - _tmp = apply(:_NormalChar) - if _tmp + while true + _tmp = apply(:_NormalChar) + break unless _tmp _ary << @result - while true - _tmp = apply(:_NormalChar) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - c1 = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end - _ary = [] + self.pos = _save1 + @result = nil + end # end repetition + c1 = @result + break unless _tmp + _ary1 = [] # kleene while true _tmp = apply(:_StrChunk) - _ary << @result if _tmp break unless _tmp + _ary1 << @result end - _tmp = true - @result = _ary + @result = _ary1 + _tmp = true # end kleene c2 = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; text(self, position, (c1+c2).join("")); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Str unless _tmp @@ -2032,159 +1587,72 @@ def _Str def _StrChunk _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] + while true - _save2 = self.pos - while true # choice + begin # choice - _save3 = self.pos - while true # sequence - _tmp = apply(:_NormalChar) - c = @result - unless _tmp - self.pos = _save3 - break - end - @result = begin; [c] ; end - _tmp = true + _save2 = self.pos + begin # sequence + _tmp = apply(:_NormalChar) + c = @result + break unless _tmp + @result = begin; [c]; end + _tmp = true + end while false unless _tmp - self.pos = _save3 - end - break - end # end sequence + self.pos = _save2 + end # end sequence - break if _tmp - self.pos = _save2 + break if _tmp - _save4 = self.pos - while true # sequence - _save5 = self.pos - _ary = [] - _tmp = match_string("_") - if _tmp - _ary << @result + _save3 = self.pos + begin # sequence + _save4 = self.pos # repetition + _ary1 = [] while true _tmp = match_string("_") - _ary << @result if _tmp break unless _tmp + _ary1 << @result end + @result = _ary1 + _tmp = _ary1.size >= 1 + unless _tmp + self.pos = _save4 + @result = nil + end # end repetition + c1 = @result + break unless _tmp + _tmp = apply(:_NormalChar) + c2 = @result + break unless _tmp + @result = begin; c1.push(c2); end _tmp = true - @result = _ary - else - self.pos = _save5 - end - c1 = @result - unless _tmp - self.pos = _save4 - break - end - _tmp = apply(:_NormalChar) - c2 = @result - unless _tmp - self.pos = _save4 - break - end - @result = begin; c1.push(c2) ; end - _tmp = true + end while false unless _tmp - self.pos = _save4 - end - break - end # end sequence + self.pos = _save3 + end # end sequence - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice - if _tmp + break unless _tmp _ary << @result - while true - - _save6 = self.pos - while true # choice - - _save7 = self.pos - while true # sequence - _tmp = apply(:_NormalChar) - c = @result - unless _tmp - self.pos = _save7 - break - end - @result = begin; [c] ; end - _tmp = true - unless _tmp - self.pos = _save7 - end - break - end # end sequence - - break if _tmp - self.pos = _save6 - - _save8 = self.pos - while true # sequence - _save9 = self.pos - _ary = [] - _tmp = match_string("_") - if _tmp - _ary << @result - while true - _tmp = match_string("_") - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save9 - end - c1 = @result - unless _tmp - self.pos = _save8 - break - end - _tmp = apply(:_NormalChar) - c2 = @result - unless _tmp - self.pos = _save8 - break - end - @result = begin; c1.push(c2) ; end - _tmp = true - unless _tmp - self.pos = _save8 - end - break - end # end sequence - - break if _tmp - self.pos = _save6 - break - end # end choice - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - cc = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end - @result = begin; cc.flatten ; end + self.pos = _save1 + @result = nil + end # end repetition + cc = @result + break unless _tmp + @result = begin; cc.flatten; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_StrChunk unless _tmp @@ -2194,19 +1662,13 @@ def _StrChunk # Endline = (LineBreak | TerminalEndline | NormalEndline) def _Endline - _save = self.pos - while true # choice + begin # choice _tmp = apply(:_LineBreak) break if _tmp - self.pos = _save _tmp = apply(:_TerminalEndline) break if _tmp - self.pos = _save _tmp = apply(:_NormalEndline) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_Endline unless _tmp return _tmp @@ -2216,105 +1678,74 @@ def _Endline def _NormalEndline _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Newline) - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos _tmp = apply(:_BlankLine) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _save2 = self.pos _tmp = match_string(">") - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save2 - unless _tmp - self.pos = _save - break - end + break unless _tmp _save3 = self.pos _tmp = apply(:_AtxStart) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save3 - unless _tmp - self.pos = _save - break - end + break unless _tmp _save4 = self.pos _save5 = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Line) - unless _tmp - self.pos = _save5 - break - end + break unless _tmp - _save6 = self.pos - while true # choice - _save7 = self.pos - _tmp = match_string("=") - if _tmp - while true - _tmp = match_string("=") - break unless _tmp - end - _tmp = true - else - self.pos = _save7 + begin # choice + _save6 = self.pos # repetition + _count = 0 + while true + _tmp = match_string("=") + break unless _tmp + _count += 1 end + _tmp = _count >= 1 + unless _tmp + self.pos = _save6 + end # end repetition break if _tmp - self.pos = _save6 - _save8 = self.pos - _tmp = match_string("-") - if _tmp - while true - _tmp = match_string("-") - break unless _tmp - end - _tmp = true - else - self.pos = _save8 + _save7 = self.pos # repetition + _count1 = 0 + while true + _tmp = match_string("-") + break unless _tmp + _count1 += 1 end - break if _tmp - self.pos = _save6 - break - end # end choice + _tmp = _count1 >= 1 + unless _tmp + self.pos = _save7 + end # end repetition + end while false # end choice - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:_Newline) - unless _tmp - self.pos = _save5 - end - break + end while false + unless _tmp + self.pos = _save5 end # end sequence - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save4 - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; text(self, position, "\n"); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_NormalEndline unless _tmp @@ -2325,28 +1756,18 @@ def _NormalEndline def _TerminalEndline _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Newline) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_Eof) - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; text(self, position, "\n"); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_TerminalEndline unless _tmp @@ -2357,23 +1778,16 @@ def _TerminalEndline def _LineBreak _save = self.pos - while true # sequence + begin # sequence _tmp = match_string(" ") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_NormalEndline) - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; linebreak(self, position); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_LineBreak unless _tmp @@ -2384,19 +1798,15 @@ def _LineBreak def _Symbol _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_SpecialChar) c = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; text(self, position, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Symbol unless _tmp @@ -2406,16 +1816,11 @@ def _Symbol # Emph = (EmphStar | EmphUl) def _Emph - _save = self.pos - while true # choice + begin # choice _tmp = apply(:_EmphStar) break if _tmp - self.pos = _save _tmp = apply(:_EmphUl) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_Emph unless _tmp return _tmp @@ -2424,16 +1829,11 @@ def _Emph # Whitespace = (Spacechar | Newline) def _Whitespace - _save = self.pos - while true # choice + begin # choice _tmp = apply(:_Spacechar) break if _tmp - self.pos = _save _tmp = apply(:_Newline) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_Whitespace unless _tmp return _tmp @@ -2443,153 +1843,71 @@ def _Whitespace def _EmphStar _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("*") - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos _tmp = apply(:_Whitespace) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end - _save2 = self.pos + break unless _tmp + _save2 = self.pos # repetition _ary = [] + while true - _save3 = self.pos - while true # choice + begin # choice - _save4 = self.pos - while true # sequence - _save5 = self.pos - _tmp = match_string("*") - _tmp = _tmp ? nil : true - self.pos = _save5 - unless _tmp - self.pos = _save4 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp + _save3 = self.pos + begin # sequence + _save4 = self.pos + _tmp = match_string("*") + _tmp = !_tmp self.pos = _save4 - break - end - @result = begin; b ; end - _tmp = true + break unless _tmp + _tmp = apply(:_Inline) + b = @result + break unless _tmp + @result = begin; b; end + _tmp = true + end while false unless _tmp - self.pos = _save4 - end - break - end # end sequence + self.pos = _save3 + end # end sequence - break if _tmp - self.pos = _save3 + break if _tmp - _save6 = self.pos - while true # sequence - _tmp = apply(:_StrongStar) - b = @result - unless _tmp - self.pos = _save6 - break - end - @result = begin; b ; end - _tmp = true + _save5 = self.pos + begin # sequence + _tmp = apply(:_StrongStar) + b = @result + break unless _tmp + @result = begin; b; end + _tmp = true + end while false unless _tmp - self.pos = _save6 - end - break - end # end sequence + self.pos = _save5 + end # end sequence - break if _tmp - self.pos = _save3 - break - end # end choice + end while false # end choice - if _tmp + break unless _tmp _ary << @result - while true - - _save7 = self.pos - while true # choice - - _save8 = self.pos - while true # sequence - _save9 = self.pos - _tmp = match_string("*") - _tmp = _tmp ? nil : true - self.pos = _save9 - unless _tmp - self.pos = _save8 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp - self.pos = _save8 - break - end - @result = begin; b ; end - _tmp = true - unless _tmp - self.pos = _save8 - end - break - end # end sequence - - break if _tmp - self.pos = _save7 - - _save10 = self.pos - while true # sequence - _tmp = apply(:_StrongStar) - b = @result - unless _tmp - self.pos = _save10 - break - end - @result = begin; b ; end - _tmp = true - unless _tmp - self.pos = _save10 - end - break - end # end sequence - - break if _tmp - self.pos = _save7 - break - end # end choice - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save2 end - c = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save2 + @result = nil + end # end repetition + c = @result + break unless _tmp _tmp = match_string("*") - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; inline_element(self, position, :em, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_EmphStar unless _tmp @@ -2600,153 +1918,71 @@ def _EmphStar def _EmphUl _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("_") - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos _tmp = apply(:_Whitespace) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end - _save2 = self.pos + break unless _tmp + _save2 = self.pos # repetition _ary = [] + while true - _save3 = self.pos - while true # choice + begin # choice - _save4 = self.pos - while true # sequence - _save5 = self.pos - _tmp = match_string("_") - _tmp = _tmp ? nil : true - self.pos = _save5 - unless _tmp - self.pos = _save4 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp + _save3 = self.pos + begin # sequence + _save4 = self.pos + _tmp = match_string("_") + _tmp = !_tmp self.pos = _save4 - break - end - @result = begin; b ; end - _tmp = true + break unless _tmp + _tmp = apply(:_Inline) + b = @result + break unless _tmp + @result = begin; b; end + _tmp = true + end while false unless _tmp - self.pos = _save4 - end - break - end # end sequence + self.pos = _save3 + end # end sequence - break if _tmp - self.pos = _save3 + break if _tmp - _save6 = self.pos - while true # sequence - _tmp = apply(:_StrongUl) - b = @result - unless _tmp - self.pos = _save6 - break - end - @result = begin; b ; end - _tmp = true + _save5 = self.pos + begin # sequence + _tmp = apply(:_StrongUl) + b = @result + break unless _tmp + @result = begin; b; end + _tmp = true + end while false unless _tmp - self.pos = _save6 - end - break - end # end sequence + self.pos = _save5 + end # end sequence - break if _tmp - self.pos = _save3 - break - end # end choice + end while false # end choice - if _tmp + break unless _tmp _ary << @result - while true - - _save7 = self.pos - while true # choice - - _save8 = self.pos - while true # sequence - _save9 = self.pos - _tmp = match_string("_") - _tmp = _tmp ? nil : true - self.pos = _save9 - unless _tmp - self.pos = _save8 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp - self.pos = _save8 - break - end - @result = begin; b ; end - _tmp = true - unless _tmp - self.pos = _save8 - end - break - end # end sequence - - break if _tmp - self.pos = _save7 - - _save10 = self.pos - while true # sequence - _tmp = apply(:_StrongUl) - b = @result - unless _tmp - self.pos = _save10 - break - end - @result = begin; b ; end - _tmp = true - unless _tmp - self.pos = _save10 - end - break - end # end sequence - - break if _tmp - self.pos = _save7 - break - end # end choice - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save2 end - c = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save2 + @result = nil + end # end repetition + c = @result + break unless _tmp _tmp = match_string("_") - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; inline_element(self, position, :em, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_EmphUl unless _tmp @@ -2756,16 +1992,11 @@ def _EmphUl # Strong = (StrongStar | StrongUl) def _Strong - _save = self.pos - while true # choice + begin # choice _tmp = apply(:_StrongStar) break if _tmp - self.pos = _save _tmp = apply(:_StrongUl) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_Strong unless _tmp return _tmp @@ -2775,99 +2006,53 @@ def _Strong def _StrongStar _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("**") - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos _tmp = apply(:_Whitespace) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end - _save2 = self.pos + break unless _tmp + _save2 = self.pos # repetition _ary = [] + while true - _save3 = self.pos - while true # sequence - _save4 = self.pos - _tmp = match_string("**") - _tmp = _tmp ? nil : true - self.pos = _save4 - unless _tmp - self.pos = _save3 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp - self.pos = _save3 - break - end - @result = begin; b ; end - _tmp = true + _save3 = self.pos + begin # sequence + _save4 = self.pos + _tmp = match_string("**") + _tmp = !_tmp + self.pos = _save4 + break unless _tmp + _tmp = apply(:_Inline) + b = @result + break unless _tmp + @result = begin; b; end + _tmp = true + end while false unless _tmp self.pos = _save3 - end - break - end # end sequence + end # end sequence - if _tmp + break unless _tmp _ary << @result - while true - - _save5 = self.pos - while true # sequence - _save6 = self.pos - _tmp = match_string("**") - _tmp = _tmp ? nil : true - self.pos = _save6 - unless _tmp - self.pos = _save5 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp - self.pos = _save5 - break - end - @result = begin; b ; end - _tmp = true - unless _tmp - self.pos = _save5 - end - break - end # end sequence - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save2 end - c = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save2 + @result = nil + end # end repetition + c = @result + break unless _tmp _tmp = match_string("**") - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; inline_element(self, position, :strong, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_StrongStar unless _tmp @@ -2878,99 +2063,53 @@ def _StrongStar def _StrongUl _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("__") - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos _tmp = apply(:_Whitespace) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end - _save2 = self.pos + break unless _tmp + _save2 = self.pos # repetition _ary = [] + while true - _save3 = self.pos - while true # sequence - _save4 = self.pos - _tmp = match_string("__") - _tmp = _tmp ? nil : true - self.pos = _save4 - unless _tmp - self.pos = _save3 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp - self.pos = _save3 - break - end - @result = begin; b ; end - _tmp = true + _save3 = self.pos + begin # sequence + _save4 = self.pos + _tmp = match_string("__") + _tmp = !_tmp + self.pos = _save4 + break unless _tmp + _tmp = apply(:_Inline) + b = @result + break unless _tmp + @result = begin; b; end + _tmp = true + end while false unless _tmp self.pos = _save3 - end - break - end # end sequence + end # end sequence - if _tmp + break unless _tmp _ary << @result - while true - - _save5 = self.pos - while true # sequence - _save6 = self.pos - _tmp = match_string("__") - _tmp = _tmp ? nil : true - self.pos = _save6 - unless _tmp - self.pos = _save5 - break - end - _tmp = apply(:_Inline) - b = @result - unless _tmp - self.pos = _save5 - break - end - @result = begin; b ; end - _tmp = true - unless _tmp - self.pos = _save5 - end - break - end # end sequence - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save2 end - c = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save2 + @result = nil + end # end repetition + c = @result + break unless _tmp _tmp = match_string("__") - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; inline_element(self, position, :strong, c); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_StrongUl unless _tmp @@ -2981,30 +2120,23 @@ def _StrongUl def _Ticks1 _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:`)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos _tmp = match_string("`") - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Ticks1 unless _tmp @@ -3015,30 +2147,23 @@ def _Ticks1 def _Ticks2 _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:``)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end + break unless _tmp _save1 = self.pos _tmp = match_string("`") - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Ticks2 unless _tmp @@ -3049,198 +2174,111 @@ def _Ticks2 def _Code _save = self.pos - while true # sequence + begin # sequence - _save1 = self.pos - while true # choice + begin # choice - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_Ticks1) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save2 - break - end - _save3 = self.pos + break unless _tmp + _save2 = self.pos # repetition _ary = [] + while true - _save4 = self.pos - while true # sequence - _save5 = self.pos - _tmp = match_string("`") - _tmp = _tmp ? nil : true - self.pos = _save5 - unless _tmp + _save3 = self.pos + begin # sequence + _save4 = self.pos + _tmp = match_string("`") + _tmp = !_tmp self.pos = _save4 - break - end - _tmp = apply(:_Nonspacechar) + break unless _tmp + _tmp = apply(:_Nonspacechar) + end while false unless _tmp - self.pos = _save4 - end - break - end # end sequence + self.pos = _save3 + end # end sequence - if _tmp + break unless _tmp _ary << @result - while true - - _save6 = self.pos - while true # sequence - _save7 = self.pos - _tmp = match_string("`") - _tmp = _tmp ? nil : true - self.pos = _save7 - unless _tmp - self.pos = _save6 - break - end - _tmp = apply(:_Nonspacechar) - unless _tmp - self.pos = _save6 - end - break - end # end sequence - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save3 end - c = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp self.pos = _save2 - break - end + @result = nil + end # end repetition + c = @result + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_Ticks1) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp @result = begin; text(self, position, c.join("")); end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save1 - _save8 = self.pos - while true # sequence + _save5 = self.pos + begin # sequence _tmp = apply(:_Ticks2) - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save8 - break - end - _save9 = self.pos - _ary = [] + break unless _tmp + _save6 = self.pos # repetition + _ary1 = [] + while true - _save10 = self.pos - while true # sequence - _save11 = self.pos - _tmp = match_string("``") - _tmp = _tmp ? nil : true - self.pos = _save11 - unless _tmp - self.pos = _save10 - break - end - _tmp = apply(:_Nonspacechar) + _save7 = self.pos + begin # sequence + _save8 = self.pos + _tmp = match_string("``") + _tmp = !_tmp + self.pos = _save8 + break unless _tmp + _tmp = apply(:_Nonspacechar) + end while false unless _tmp - self.pos = _save10 - end - break - end # end sequence - - if _tmp - _ary << @result - while true + self.pos = _save7 + end # end sequence - _save12 = self.pos - while true # sequence - _save13 = self.pos - _tmp = match_string("``") - _tmp = _tmp ? nil : true - self.pos = _save13 - unless _tmp - self.pos = _save12 - break - end - _tmp = apply(:_Nonspacechar) - unless _tmp - self.pos = _save12 - end - break - end # end sequence - - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save9 + break unless _tmp + _ary1 << @result end - c = @result + @result = _ary1 + _tmp = _ary1.size >= 1 unless _tmp - self.pos = _save8 - break - end + self.pos = _save6 + @result = nil + end # end repetition + c = @result + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = apply(:_Ticks2) - unless _tmp - self.pos = _save8 - break - end + break unless _tmp @result = begin; text(self, position, c.join("")); end _tmp = true - unless _tmp - self.pos = _save8 - end - break + end while false + unless _tmp + self.pos = _save5 end # end sequence - break if _tmp - self.pos = _save1 - break - end # end choice + end while false # end choice cc = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; inline_element(self, position, :code, [cc]); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Code unless _tmp @@ -3251,17 +2289,13 @@ def _Code def _BlankLine _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save - break - end - _tmp = apply(:_Newline) - unless _tmp - self.pos = _save - end - break + break unless _tmp + _tmp = apply(:_Newline) + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_BlankLine unless _tmp @@ -3271,96 +2305,69 @@ def _BlankLine # Quoted = ("\"" (!"\"" .)* "\"" | "'" (!"'" .)* "'") def _Quoted - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = match_string("\"") - unless _tmp - self.pos = _save1 - break - end - while true + break unless _tmp + while true # kleene - _save3 = self.pos - while true # sequence - _save4 = self.pos + _save1 = self.pos + begin # sequence + _save2 = self.pos _tmp = match_string("\"") - _tmp = _tmp ? nil : true - self.pos = _save4 - unless _tmp - self.pos = _save3 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save3 - end - break + _tmp = !_tmp + self.pos = _save2 + break unless _tmp + _tmp = match_dot + end while false + unless _tmp + self.pos = _save1 end # end sequence break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save1 - break - end + _tmp = true # end kleene + break unless _tmp _tmp = match_string("\"") - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save5 = self.pos - while true # sequence + _save3 = self.pos + begin # sequence _tmp = match_string("'") - unless _tmp - self.pos = _save5 - break - end - while true + break unless _tmp + while true # kleene - _save7 = self.pos - while true # sequence - _save8 = self.pos + _save4 = self.pos + begin # sequence + _save5 = self.pos _tmp = match_string("'") - _tmp = _tmp ? nil : true - self.pos = _save8 - unless _tmp - self.pos = _save7 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save7 - end - break + _tmp = !_tmp + self.pos = _save5 + break unless _tmp + _tmp = match_dot + end while false + unless _tmp + self.pos = _save4 end # end sequence break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save5 - break - end + _tmp = true # end kleene + break unless _tmp _tmp = match_string("'") - unless _tmp - self.pos = _save5 - end - break + end while false + unless _tmp + self.pos = _save3 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_Quoted unless _tmp return _tmp @@ -3369,8 +2376,8 @@ def _Quoted # Eof = !. def _Eof _save = self.pos - _tmp = get_byte - _tmp = _tmp ? nil : true + _tmp = match_dot + _tmp = !_tmp self.pos = _save set_failed_rule :_Eof unless _tmp return _tmp @@ -3380,22 +2387,18 @@ def _Eof def _Spacechar _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix: |\t)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Spacechar unless _tmp @@ -3406,38 +2409,28 @@ def _Spacechar def _Nonspacechar _save = self.pos - while true # sequence + begin # sequence _save1 = self.pos _tmp = apply(:_Spacechar) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save1 - unless _tmp - self.pos = _save - break - end + break unless _tmp _save2 = self.pos _tmp = apply(:_Newline) - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save2 - unless _tmp - self.pos = _save - break - end + break unless _tmp _text_start = self.pos - _tmp = get_byte + _tmp = match_dot if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Nonspacechar unless _tmp @@ -3447,35 +2440,23 @@ def _Nonspacechar # Newline = ("\n" | "\r" "\n"?) def _Newline - _save = self.pos - while true # choice + begin # choice _tmp = match_string("\n") break if _tmp - self.pos = _save - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = match_string("\r") - unless _tmp - self.pos = _save1 - break - end - _save2 = self.pos + break unless _tmp + # optional _tmp = match_string("\n") - unless _tmp - _tmp = true - self.pos = _save2 - end - unless _tmp - self.pos = _save1 - end - break + _tmp = true # end optional + end while false + unless _tmp + self.pos = _save end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_Newline unless _tmp return _tmp @@ -3483,11 +2464,11 @@ def _Newline # Sp = Spacechar* def _Sp - while true + while true # kleene _tmp = apply(:_Spacechar) break unless _tmp end - _tmp = true + _tmp = true # end kleene set_failed_rule :_Sp unless _tmp return _tmp end @@ -3496,36 +2477,25 @@ def _Sp def _Spnl _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_Sp) - unless _tmp - self.pos = _save - break - end - _save1 = self.pos + break unless _tmp + # optional - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_Newline) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_Sp) - unless _tmp - self.pos = _save2 - end - break - end # end sequence - + end while false unless _tmp - _tmp = true self.pos = _save1 - end - unless _tmp - self.pos = _save - end - break + end # end sequence + + _tmp = true # end optional + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_Spnl unless _tmp @@ -3536,22 +2506,18 @@ def _Spnl def _SpecialChar _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[~*_`&\[\]()= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -422,22 +433,18 @@ def _space def _alpha _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[A-Za-z])/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text.upcase ; end + break unless _tmp + @result = begin; text.upcase; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_alpha unless _tmp @@ -447,78 +454,54 @@ def _alpha # word = (alpha:a word:w { "#{a}#{w}" } | alpha:a space { "#{a} "} | alpha:a { a }) def _word - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_alpha) a = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_word) w = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; "#{a}#{w}" ; end + break unless _tmp + @result = begin; "#{a}#{w}"; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_alpha) a = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_space) - unless _tmp - self.pos = _save2 - break - end - @result = begin; "#{a} "; end + break unless _tmp + @result = begin; "#{a} "; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save - _save3 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = apply(:_alpha) a = @result - unless _tmp - self.pos = _save3 - break - end - @result = begin; a ; end + break unless _tmp + @result = begin; a; end _tmp = true - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save2 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_word unless _tmp return _tmp @@ -527,54 +510,38 @@ def _word # sentence = (word:w sentence:s { "#{w}#{s}" } | word:w { w }) def _sentence - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_word) w = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_sentence) s = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; "#{w}#{s}" ; end + break unless _tmp + @result = begin; "#{w}#{s}"; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_word) w = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; w ; end + break unless _tmp + @result = begin; w; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_sentence unless _tmp return _tmp @@ -583,92 +550,62 @@ def _sentence # document = (sentence:s period space* document:d { "#{s}. #{d}" } | sentence:s period { "#{s}." } | sentence:s { "#{s}" }) def _document - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_sentence) s = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_period) - unless _tmp - self.pos = _save1 - break - end - while true + break unless _tmp + while true # kleene _tmp = apply(:_space) break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save1 - break - end + _tmp = true # end kleene + break unless _tmp _tmp = apply(:_document) d = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; "#{s}. #{d}" ; end + break unless _tmp + @result = begin; "#{s}. #{d}"; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save3 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_sentence) s = @result - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = apply(:_period) - unless _tmp - self.pos = _save3 - break - end - @result = begin; "#{s}." ; end + break unless _tmp + @result = begin; "#{s}."; end _tmp = true - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save - _save4 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = apply(:_sentence) s = @result - unless _tmp - self.pos = _save4 - break - end - @result = begin; "#{s}" ; end + break unless _tmp + @result = begin; "#{s}"; end _tmp = true - unless _tmp - self.pos = _save4 - end - break + end while false + unless _tmp + self.pos = _save2 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_document unless _tmp return _tmp @@ -678,19 +615,15 @@ def _document def _root _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_document) d = @result - unless _tmp - self.pos = _save - break - end - @result = begin; @output = d ; end + break unless _tmp + @result = begin; @output = d; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp diff --git a/lib/kpeg/code_generator.rb b/lib/kpeg/code_generator.rb index 5da0590..e1d7a43 100644 --- a/lib/kpeg/code_generator.rb +++ b/lib/kpeg/code_generator.rb @@ -7,7 +7,7 @@ def initialize(name, gram, debug=false) @name = name @grammar = gram @debug = debug - @saves = 0 + @saves = Hash.new(0) @output = nil @standalone = false end @@ -19,19 +19,14 @@ def method_name(name) "_#{name}" end - def save - if @saves == 0 - str = "_save" - else - str = "_save#{@saves}" - end - - @saves += 1 - str + def save(name="_save") + cnt = @saves[name] + @saves[name] = cnt + 1 + cnt == 0 ? name : "#{name}#{cnt}" end def reset_saves - @saves = 0 + @saves.clear end def output_ast(short, code, description) @@ -102,7 +97,7 @@ def indentify(code, indent) def output_op(code, op, indent=2) case op when Dot - code << indentify("_tmp = get_byte\n", indent) + code << indentify("_tmp = match_dot\n", indent) when LiteralString code << indentify("_tmp = match_string(#{op.string.dump})\n", indent) when LiteralRegexp @@ -114,12 +109,7 @@ def output_op(code, op, indent=2) end code << indentify("_tmp = scan(/\\G#{op.regexp}/#{lang})\n", indent) when CharRange - ss = save() if op.start.bytesize == 1 and op.fin.bytesize == 1 - code << indentify("#{ss} = self.pos\n", indent) - code << indentify("_tmp = get_byte\n", indent) - code << indentify("if _tmp\n", indent) - if op.start.respond_to? :getbyte left = op.start.getbyte 0 right = op.fin.getbyte 0 @@ -128,129 +118,101 @@ def output_op(code, op, indent=2) right = op.fin[0] end - code << indentify(" unless _tmp >= #{left} and _tmp <= #{right}\n", indent) - code << indentify(" self.pos = #{ss}\n", indent) - code << indentify(" _tmp = nil\n", indent) - code << indentify(" end\n", indent) - code << indentify("end\n", indent) + code << indentify("_tmp = match_char_range(#{left}..#{right})\n", indent) else raise "Unsupported char range - #{op.inspect}" end when Choice - ss = save() code << "\n" - code << indentify("#{ss} = self.pos\n", indent) - code << indentify("while true # choice\n", indent) + code << indentify("begin # choice\n", indent) op.ops.each_with_index do |n,idx| - output_op code, n, (indent+1) - - code << indentify(" break if _tmp\n", indent) - code << indentify(" self.pos = #{ss}\n", indent) - if idx == op.ops.size - 1 - code << indentify(" break\n", indent) + if idx > 0 + code << indentify(" break if _tmp\n", indent) end + output_op code, n, (indent+1) end - code << indentify("end # end choice\n\n", indent) + code << indentify("end while false # end choice\n\n", indent) when Multiple - ss = save() if op.min == 0 and op.max == 1 - code << indentify("#{ss} = self.pos\n", indent) + code << indentify("# optional\n", indent) output_op code, op.op, indent if op.save_values code << indentify("@result = nil unless _tmp\n", indent) end - code << indentify("unless _tmp\n", indent) - code << indentify(" _tmp = true\n", indent) - code << indentify(" self.pos = #{ss}\n", indent) - code << indentify("end\n", indent) + code << indentify("_tmp = true # end optional\n", indent) elsif op.min == 0 and !op.max if op.save_values - code << indentify("_ary = []\n", indent) + ary = save("_ary") + code << indentify("#{ary} = [] # kleene\n", indent) + code << indentify("while true\n", indent) + else + code << indentify("while true # kleene\n", indent) end - code << indentify("while true\n", indent) output_op code, op.op, (indent+1) + code << indentify(" break unless _tmp\n", indent) if op.save_values - code << indentify(" _ary << @result if _tmp\n", indent) + code << indentify(" #{ary} << @result\n", indent) end - code << indentify(" break unless _tmp\n", indent) code << indentify("end\n", indent) - code << indentify("_tmp = true\n", indent) - if op.save_values - code << indentify("@result = _ary\n", indent) + code << indentify("@result = #{ary}\n", indent) end + code << indentify("_tmp = true # end kleene\n", indent) - elsif op.min == 1 and !op.max - code << indentify("#{ss} = self.pos\n", indent) + else + ss = save() + code << indentify("#{ss} = self.pos # repetition\n", indent) if op.save_values - code << indentify("_ary = []\n", indent) + ary = save("_ary") + incr = "#{ary} << @result" + cnt = "#{ary}.size" + code << indentify("#{ary} = []\n", indent) + else + cnt = save("_count") + incr = "#{cnt} += 1" + code << indentify("#{cnt} = 0\n", indent) end - output_op code, op.op, indent - code << indentify("if _tmp\n", indent) - if op.save_values - code << indentify(" _ary << @result\n", indent) + code << indentify("while true\n", indent) + output_op code, op.op, (indent+1) + code << indentify(" break unless _tmp\n", indent) + code << indentify(" #{incr}\n", indent) + if op.max + code << indentify(" break if #{cnt} == #{op.max}\n", indent) end - code << indentify(" while true\n", indent) - output_op code, op.op, (indent+2) + code << indentify("end\n", indent) if op.save_values - code << indentify(" _ary << @result if _tmp\n", indent) + code << indentify("@result = #{ary}\n", indent) end - code << indentify(" break unless _tmp\n", indent) - code << indentify(" end\n", indent) - code << indentify(" _tmp = true\n", indent) + code << indentify("_tmp = #{cnt} >= #{op.min}\n", indent) + code << indentify("unless _tmp\n", indent) + code << indentify(" self.pos = #{ss}\n", indent) if op.save_values - code << indentify(" @result = _ary\n", indent) + code << indentify(" @result = nil\n", indent) end - code << indentify("else\n", indent) - code << indentify(" self.pos = #{ss}\n", indent) - code << indentify("end\n", indent) - else - code << indentify("#{ss} = self.pos\n", indent) - code << indentify("_count = 0\n", indent) - code << indentify("while true\n", indent) - output_op code, op.op, (indent+1) - code << indentify(" if _tmp\n", indent) - code << indentify(" _count += 1\n", indent) - code << indentify(" break if _count == #{op.max}\n", indent) - code << indentify(" else\n", indent) - code << indentify(" break\n", indent) - code << indentify(" end\n", indent) - code << indentify("end\n", indent) - code << indentify("if _count >= #{op.min}\n", indent) - code << indentify(" _tmp = true\n", indent) - code << indentify("else\n", indent) - code << indentify(" self.pos = #{ss}\n", indent) - code << indentify(" _tmp = nil\n", indent) - code << indentify("end\n", indent) + code << indentify("end # end repetition\n", indent) end when Sequence ss = save() code << "\n" code << indentify("#{ss} = self.pos\n", indent) - code << indentify("while true # sequence\n", indent) + code << indentify("begin # sequence\n", indent) op.ops.each_with_index do |n, idx| - output_op code, n, (indent+1) - - if idx == op.ops.size - 1 - code << indentify(" unless _tmp\n", indent) - code << indentify(" self.pos = #{ss}\n", indent) - code << indentify(" end\n", indent) - code << indentify(" break\n", indent) - else - code << indentify(" unless _tmp\n", indent) - code << indentify(" self.pos = #{ss}\n", indent) - code << indentify(" break\n", indent) - code << indentify(" end\n", indent) + if idx > 0 + code << indentify(" break unless _tmp\n", indent) end + output_op code, n, (indent+1) end + code << indentify("end while false\n", indent) + code << indentify("unless _tmp\n", indent) + code << indentify(" self.pos = #{ss}\n", indent) code << indentify("end # end sequence\n\n", indent) when AndPredicate ss = save() code << indentify("#{ss} = self.pos\n", indent) if op.op.kind_of? Action - code << indentify("_tmp = begin; #{op.op.action}; end\n", indent) + code << indentify("_tmp = begin; #{op.op.action.strip}; end\n", indent) else output_op code, op.op, indent end @@ -259,11 +221,11 @@ def output_op(code, op, indent=2) ss = save() code << indentify("#{ss} = self.pos\n", indent) if op.op.kind_of? Action - code << indentify("_tmp = begin; #{op.op.action}; end\n", indent) + code << indentify("_tmp = begin; #{op.op.action.strip}; end\n", indent) else output_op code, op.op, indent end - code << indentify("_tmp = _tmp ? nil : true\n", indent) + code << indentify("_tmp = !_tmp\n", indent) code << indentify("self.pos = #{ss}\n", indent) when RuleReference if op.arguments @@ -284,15 +246,13 @@ def output_op(code, op, indent=2) code << indentify("_tmp = @_grammar_#{op.grammar_name}.external_invoke(self, :#{method_name op.rule_name})\n", indent) end when Tag + output_op code, op.op, indent if op.tag_name and !op.tag_name.empty? - output_op code, op.op, indent code << indentify("#{op.tag_name} = @result\n", indent) - else - output_op code, op.op, indent end when Action code << indentify("@result = begin; ", indent) - code << op.action << "; end\n" + code << op.action.strip << "; end\n" if @debug code << indentify("puts \" => \" #{op.action.dump} \" => \#{@result.inspect} \\n\"\n", indent) end diff --git a/lib/kpeg/compiled_parser.rb b/lib/kpeg/compiled_parser.rb index 34eee77..4b2f4f6 100644 --- a/lib/kpeg/compiled_parser.rb +++ b/lib/kpeg/compiled_parser.rb @@ -131,6 +131,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -151,24 +160,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end diff --git a/lib/kpeg/format_parser.rb b/lib/kpeg/format_parser.rb index c9aa51d..b5991ed 100644 --- a/lib/kpeg/format_parser.rb +++ b/lib/kpeg/format_parser.rb @@ -189,6 +189,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -209,24 +218,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -421,38 +432,30 @@ def _eol def _eof_comment _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("#") - unless _tmp - self.pos = _save - break - end - while true + break unless _tmp + while true # kleene - _save2 = self.pos - while true # sequence - _save3 = self.pos + _save1 = self.pos + begin # sequence + _save2 = self.pos _tmp = apply(:_eof) - _tmp = _tmp ? nil : true - self.pos = _save3 - unless _tmp - self.pos = _save2 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save2 - end - break + _tmp = !_tmp + self.pos = _save2 + break unless _tmp + _tmp = match_dot + end while false + unless _tmp + self.pos = _save1 end # end sequence break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - end - break + _tmp = true # end kleene + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_eof_comment unless _tmp @@ -463,43 +466,32 @@ def _eof_comment def _comment _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("#") - unless _tmp - self.pos = _save - break - end - while true + break unless _tmp + while true # kleene - _save2 = self.pos - while true # sequence - _save3 = self.pos + _save1 = self.pos + begin # sequence + _save2 = self.pos _tmp = apply(:_eol) - _tmp = _tmp ? nil : true - self.pos = _save3 - unless _tmp - self.pos = _save2 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save2 - end - break + _tmp = !_tmp + self.pos = _save2 + break unless _tmp + _tmp = match_dot + end while false + unless _tmp + self.pos = _save1 end # end sequence break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - break - end + _tmp = true # end kleene + break unless _tmp _tmp = apply(:_eol) - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_comment unless _tmp @@ -509,19 +501,13 @@ def _comment # space = (" " | "\t" | eol) def _space - _save = self.pos - while true # choice + begin # choice _tmp = match_string(" ") break if _tmp - self.pos = _save _tmp = match_string("\t") break if _tmp - self.pos = _save _tmp = apply(:_eol) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_space unless _tmp return _tmp @@ -529,22 +515,17 @@ def _space # - = (space | comment)* def __hyphen_ - while true + while true # kleene - _save1 = self.pos - while true # choice + begin # choice _tmp = apply(:_space) break if _tmp - self.pos = _save1 _tmp = apply(:_comment) - break if _tmp - self.pos = _save1 - break - end # end choice + end while false # end choice break unless _tmp end - _tmp = true + _tmp = true # end kleene set_failed_rule :__hyphen_ unless _tmp return _tmp end @@ -560,33 +541,24 @@ def _kleene def _var _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - _save1 = self.pos - while true # choice + begin # choice _tmp = match_string("-") break if _tmp - self.pos = _save1 _tmp = scan(/\G(?i-mx:[a-z][\w-]*)/) - break if _tmp - self.pos = _save1 - break - end # end choice + end while false # end choice if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_var unless _tmp @@ -597,22 +569,18 @@ def _var def _method _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?i-mx:[a-z_]\w*)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_method unless _tmp @@ -622,233 +590,169 @@ def _method # dbl_escapes = ("n" { "\n" } | "s" { " " } | "r" { "\r" } | "t" { "\t" } | "v" { "\v" } | "f" { "\f" } | "b" { "\b" } | "a" { "\a" } | "e" { "\e" } | "\\" { "\\" } | "\"" { "\"" } | num_escapes | < . > { text }) def _dbl_escapes - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = match_string("n") - unless _tmp - self.pos = _save1 - break - end - @result = begin; "\n" ; end + break unless _tmp + @result = begin; "\n"; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = match_string("s") - unless _tmp - self.pos = _save2 - break - end - @result = begin; " " ; end + break unless _tmp + @result = begin; " "; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save - _save3 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = match_string("r") - unless _tmp - self.pos = _save3 - break - end - @result = begin; "\r" ; end + break unless _tmp + @result = begin; "\r"; end _tmp = true - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save2 end # end sequence break if _tmp - self.pos = _save - _save4 = self.pos - while true # sequence + _save3 = self.pos + begin # sequence _tmp = match_string("t") - unless _tmp - self.pos = _save4 - break - end - @result = begin; "\t" ; end + break unless _tmp + @result = begin; "\t"; end _tmp = true - unless _tmp - self.pos = _save4 - end - break + end while false + unless _tmp + self.pos = _save3 end # end sequence break if _tmp - self.pos = _save - _save5 = self.pos - while true # sequence + _save4 = self.pos + begin # sequence _tmp = match_string("v") - unless _tmp - self.pos = _save5 - break - end - @result = begin; "\v" ; end + break unless _tmp + @result = begin; "\v"; end _tmp = true - unless _tmp - self.pos = _save5 - end - break + end while false + unless _tmp + self.pos = _save4 end # end sequence break if _tmp - self.pos = _save - _save6 = self.pos - while true # sequence + _save5 = self.pos + begin # sequence _tmp = match_string("f") - unless _tmp - self.pos = _save6 - break - end - @result = begin; "\f" ; end + break unless _tmp + @result = begin; "\f"; end _tmp = true - unless _tmp - self.pos = _save6 - end - break + end while false + unless _tmp + self.pos = _save5 end # end sequence break if _tmp - self.pos = _save - _save7 = self.pos - while true # sequence + _save6 = self.pos + begin # sequence _tmp = match_string("b") - unless _tmp - self.pos = _save7 - break - end - @result = begin; "\b" ; end + break unless _tmp + @result = begin; "\b"; end _tmp = true - unless _tmp - self.pos = _save7 - end - break + end while false + unless _tmp + self.pos = _save6 end # end sequence break if _tmp - self.pos = _save - _save8 = self.pos - while true # sequence + _save7 = self.pos + begin # sequence _tmp = match_string("a") - unless _tmp - self.pos = _save8 - break - end - @result = begin; "\a" ; end + break unless _tmp + @result = begin; "\a"; end _tmp = true - unless _tmp - self.pos = _save8 - end - break + end while false + unless _tmp + self.pos = _save7 end # end sequence break if _tmp - self.pos = _save - _save9 = self.pos - while true # sequence + _save8 = self.pos + begin # sequence _tmp = match_string("e") - unless _tmp - self.pos = _save9 - break - end - @result = begin; "\e" ; end + break unless _tmp + @result = begin; "\e"; end _tmp = true - unless _tmp - self.pos = _save9 - end - break + end while false + unless _tmp + self.pos = _save8 end # end sequence break if _tmp - self.pos = _save - _save10 = self.pos - while true # sequence + _save9 = self.pos + begin # sequence _tmp = match_string("\\") - unless _tmp - self.pos = _save10 - break - end - @result = begin; "\\" ; end + break unless _tmp + @result = begin; "\\"; end _tmp = true - unless _tmp - self.pos = _save10 - end - break + end while false + unless _tmp + self.pos = _save9 end # end sequence break if _tmp - self.pos = _save - _save11 = self.pos - while true # sequence + _save10 = self.pos + begin # sequence _tmp = match_string("\"") - unless _tmp - self.pos = _save11 - break - end - @result = begin; "\"" ; end + break unless _tmp + @result = begin; "\""; end _tmp = true - unless _tmp - self.pos = _save11 - end - break + end while false + unless _tmp + self.pos = _save10 end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_num_escapes) break if _tmp - self.pos = _save - _save12 = self.pos - while true # sequence + _save11 = self.pos + begin # sequence _text_start = self.pos - _tmp = get_byte + _tmp = match_dot if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save12 - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save12 - end - break + end while false + unless _tmp + self.pos = _save11 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_dbl_escapes unless _tmp return _tmp @@ -857,59 +761,43 @@ def _dbl_escapes # num_escapes = (< /[0-7]{1,3}/ > { [text.to_i(8)].pack("U") } | "x" < /[a-f\d]{2}/i > { [text.to_i(16)].pack("U") }) def _num_escapes - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[0-7]{1,3})/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save1 - break - end - @result = begin; [text.to_i(8)].pack("U") ; end + break unless _tmp + @result = begin; [text.to_i(8)].pack("U"); end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = match_string("x") - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _text_start = self.pos _tmp = scan(/\G(?i-mx:[a-f\d]{2})/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save2 - break - end - @result = begin; [text.to_i(16)].pack("U") ; end + break unless _tmp + @result = begin; [text.to_i(16)].pack("U"); end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_num_escapes unless _tmp return _tmp @@ -919,22 +807,18 @@ def _num_escapes def _dbl_seq _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[^\\"]+)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_dbl_seq unless _tmp @@ -945,51 +829,38 @@ def _dbl_seq def _dbl_not_quote _save = self.pos - while true # sequence - _ary = [] + begin # sequence + _ary = [] # kleene while true - _save2 = self.pos - while true # choice + begin # choice - _save3 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = match_string("\\") - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = apply(:_dbl_escapes) - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save2 _tmp = apply(:_dbl_seq) - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene ary = @result - unless _tmp - self.pos = _save - break - end - @result = begin; Array(ary) ; end + break unless _tmp + @result = begin; Array(ary); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_dbl_not_quote unless _tmp @@ -1000,29 +871,19 @@ def _dbl_not_quote def _dbl_string _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("\"") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_dbl_not_quote) s = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("\"") - unless _tmp - self.pos = _save - break - end - @result = begin; @g.str(s.join) ; end + break unless _tmp + @result = begin; @g.str(s.join); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_dbl_string unless _tmp @@ -1033,18 +894,14 @@ def _dbl_string def _sgl_escape_quote _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("\\'") - unless _tmp - self.pos = _save - break - end - @result = begin; "'" ; end + break unless _tmp + @result = begin; "'"; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_sgl_escape_quote unless _tmp @@ -1055,22 +912,18 @@ def _sgl_escape_quote def _sgl_seq _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[^'])/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_sgl_seq unless _tmp @@ -1081,37 +934,28 @@ def _sgl_seq def _sgl_not_quote _save = self.pos - while true # sequence - _ary = [] + begin # sequence + _ary = [] # kleene while true - _save2 = self.pos - while true # choice + begin # choice _tmp = apply(:_sgl_escape_quote) break if _tmp - self.pos = _save2 _tmp = apply(:_sgl_seq) - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene segs = @result - unless _tmp - self.pos = _save - break - end - @result = begin; Array(segs) ; end + break unless _tmp + @result = begin; Array(segs); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_sgl_not_quote unless _tmp @@ -1122,29 +966,19 @@ def _sgl_not_quote def _sgl_string _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("'") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_sgl_not_quote) s = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("'") - unless _tmp - self.pos = _save - break - end - @result = begin; @g.str(s.join) ; end + break unless _tmp + @result = begin; @g.str(s.join); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_sgl_string unless _tmp @@ -1154,16 +988,11 @@ def _sgl_string # string = (dbl_string | sgl_string) def _string - _save = self.pos - while true # choice + begin # choice _tmp = apply(:_dbl_string) break if _tmp - self.pos = _save _tmp = apply(:_sgl_string) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_string unless _tmp return _tmp @@ -1173,54 +1002,34 @@ def _string def _not_slash _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - _save1 = self.pos - - _save2 = self.pos - while true # choice - _tmp = match_string("\\/") - break if _tmp - self.pos = _save2 - _tmp = scan(/\G(?-mix:[^\/])/) - break if _tmp - self.pos = _save2 - break - end # end choice - - if _tmp - while true + _save1 = self.pos # repetition + _count = 0 + while true - _save3 = self.pos - while true # choice - _tmp = match_string("\\/") - break if _tmp - self.pos = _save3 - _tmp = scan(/\G(?-mix:[^\/])/) - break if _tmp - self.pos = _save3 - break - end # end choice + begin # choice + _tmp = match_string("\\/") + break if _tmp + _tmp = scan(/\G(?-mix:[^\/])/) + end while false # end choice - break unless _tmp - end - _tmp = true - else - self.pos = _save1 + break unless _tmp + _count += 1 end + _tmp = _count >= 1 + unless _tmp + self.pos = _save1 + end # end repetition if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_not_slash unless _tmp @@ -1231,33 +1040,22 @@ def _not_slash def _regexp_opts _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - while true - _save2 = self.pos - _tmp = get_byte - if _tmp - unless _tmp >= 97 and _tmp <= 122 - self.pos = _save2 - _tmp = nil - end - end + while true # kleene + _tmp = match_char_range(97..122) break unless _tmp end - _tmp = true + _tmp = true # end kleene if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_regexp_opts unless _tmp @@ -1268,35 +1066,22 @@ def _regexp_opts def _regexp _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("/") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_not_slash) body = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("/") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_regexp_opts) opts = @result - unless _tmp - self.pos = _save - break - end - @result = begin; @g.reg body, opts ; end + break unless _tmp + @result = begin; @g.reg body, opts; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_regexp unless _tmp @@ -1307,22 +1092,18 @@ def _regexp def _char _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?i-mx:[a-z\d])/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_char unless _tmp @@ -1333,40 +1114,24 @@ def _char def _char_range _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("[") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_char) l = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("-") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_char) r = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("]") - unless _tmp - self.pos = _save - break - end - @result = begin; @g.range(l,r) ; end + break unless _tmp + @result = begin; @g.range(l,r); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_char_range unless _tmp @@ -1377,22 +1142,18 @@ def _char_range def _range_num _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[1-9]\d*)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_range_num unless _tmp @@ -1403,33 +1164,24 @@ def _range_num def _range_elem _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos - _save1 = self.pos - while true # choice + begin # choice _tmp = apply(:_range_num) break if _tmp - self.pos = _save1 _tmp = apply(:_kleene) - break if _tmp - self.pos = _save1 - break - end # end choice + end while false # end choice if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_range_elem unless _tmp @@ -1439,109 +1191,60 @@ def _range_elem # mult_range = ("[" - range_elem:l - "," - range_elem:r - "]" { [l == "*" ? nil : l.to_i, r == "*" ? nil : r.to_i] } | "[" - range_num:e - "]" { [e.to_i, e.to_i] }) def _mult_range - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = match_string("[") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_range_elem) l = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string(",") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_range_elem) r = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string("]") - unless _tmp - self.pos = _save1 - break - end - @result = begin; [l == "*" ? nil : l.to_i, r == "*" ? nil : r.to_i] ; end + break unless _tmp + @result = begin; [l == "*" ? nil : l.to_i, r == "*" ? nil : r.to_i]; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = match_string("[") - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_range_num) e = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = match_string("]") - unless _tmp - self.pos = _save2 - break - end - @result = begin; [e.to_i, e.to_i] ; end + break unless _tmp + @result = begin; [e.to_i, e.to_i]; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_mult_range unless _tmp return _tmp @@ -1558,53 +1261,36 @@ def _curly_block def _curly _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("{") - unless _tmp - self.pos = _save - break - end + break unless _tmp _text_start = self.pos - while true + while true # kleene - _save2 = self.pos - while true # choice + begin # choice _tmp = apply(:_spaces) break if _tmp - self.pos = _save2 _tmp = scan(/\G(?-mix:[^{}"']+)/) break if _tmp - self.pos = _save2 _tmp = apply(:_string) break if _tmp - self.pos = _save2 _tmp = apply(:_curly) - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice break unless _tmp end - _tmp = true + _tmp = true # end kleene if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("}") - unless _tmp - self.pos = _save - break - end - @result = begin; @g.action(text) ; end + break unless _tmp + @result = begin; @g.action(text); end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_curly unless _tmp @@ -1615,40 +1301,27 @@ def _curly def _nested_paren _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("(") - unless _tmp - self.pos = _save - break - end - while true + break unless _tmp + while true # kleene - _save2 = self.pos - while true # choice + begin # choice _tmp = scan(/\G(?-mix:[^()"']+)/) break if _tmp - self.pos = _save2 _tmp = apply(:_string) break if _tmp - self.pos = _save2 _tmp = apply(:_nested_paren) - break if _tmp - self.pos = _save2 - break - end # end choice + end while false # end choice break unless _tmp end - _tmp = true - unless _tmp - self.pos = _save - break - end + _tmp = true # end kleene + break unless _tmp _tmp = match_string(")") - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_nested_paren unless _tmp @@ -1658,572 +1331,363 @@ def _nested_paren # value = (value:v ":" var:n { @g.t(v,n) } | value:v "?" { @g.maybe(v) } | value:v "+" { @g.many(v) } | value:v "*" { @g.kleene(v) } | value:v mult_range:r { @g.multiple(v, *r) } | "&" value:v { @g.andp(v) } | "!" value:v { @g.notp(v) } | "(" - expression:o - ")" { o } | "@<" - expression:o - ">" { @g.bounds(o) } | "<" - expression:o - ">" { @g.collect(o) } | curly_block | "~" method:m < nested_paren? > { @g.action("#{m}#{text}") } | "." { @g.dot } | "@" var:name < nested_paren? > !(- "=") { @g.invoke(name, text.empty? ? nil : text) } | "^" var:name < nested_paren? > { @g.foreign_invoke("parent", name, text) } | "%" var:gram "." var:name < nested_paren? > { @g.foreign_invoke(gram, name, text) } | var:name < nested_paren? > !(- "=") { @g.ref(name, nil, text.empty? ? nil : text) } | char_range | regexp | string) def _value - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string(":") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_var) n = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; @g.t(v,n) ; end + break unless _tmp + @result = begin; @g.t(v,n); end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = match_string("?") - unless _tmp - self.pos = _save2 - break - end - @result = begin; @g.maybe(v) ; end + break unless _tmp + @result = begin; @g.maybe(v); end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save - _save3 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = match_string("+") - unless _tmp - self.pos = _save3 - break - end - @result = begin; @g.many(v) ; end + break unless _tmp + @result = begin; @g.many(v); end _tmp = true - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save2 end # end sequence break if _tmp - self.pos = _save - _save4 = self.pos - while true # sequence + _save3 = self.pos + begin # sequence _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save4 - break - end + break unless _tmp _tmp = match_string("*") - unless _tmp - self.pos = _save4 - break - end - @result = begin; @g.kleene(v) ; end + break unless _tmp + @result = begin; @g.kleene(v); end _tmp = true - unless _tmp - self.pos = _save4 - end - break + end while false + unless _tmp + self.pos = _save3 end # end sequence break if _tmp - self.pos = _save - _save5 = self.pos - while true # sequence + _save4 = self.pos + begin # sequence _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:_mult_range) r = @result - unless _tmp - self.pos = _save5 - break - end - @result = begin; @g.multiple(v, *r) ; end + break unless _tmp + @result = begin; @g.multiple(v, *r); end _tmp = true - unless _tmp - self.pos = _save5 - end - break + end while false + unless _tmp + self.pos = _save4 end # end sequence break if _tmp - self.pos = _save - _save6 = self.pos - while true # sequence + _save5 = self.pos + begin # sequence _tmp = match_string("&") - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save6 - break - end - @result = begin; @g.andp(v) ; end + break unless _tmp + @result = begin; @g.andp(v); end _tmp = true - unless _tmp - self.pos = _save6 - end - break + end while false + unless _tmp + self.pos = _save5 end # end sequence break if _tmp - self.pos = _save - _save7 = self.pos - while true # sequence + _save6 = self.pos + begin # sequence _tmp = match_string("!") - unless _tmp - self.pos = _save7 - break - end + break unless _tmp _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save7 - break - end - @result = begin; @g.notp(v) ; end + break unless _tmp + @result = begin; @g.notp(v); end _tmp = true - unless _tmp - self.pos = _save7 - end - break + end while false + unless _tmp + self.pos = _save6 end # end sequence break if _tmp - self.pos = _save - _save8 = self.pos - while true # sequence + _save7 = self.pos + begin # sequence _tmp = match_string("(") - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = apply(:_expression) o = @result - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save8 - break - end + break unless _tmp _tmp = match_string(")") - unless _tmp - self.pos = _save8 - break - end - @result = begin; o ; end + break unless _tmp + @result = begin; o; end _tmp = true - unless _tmp - self.pos = _save8 - end - break + end while false + unless _tmp + self.pos = _save7 end # end sequence break if _tmp - self.pos = _save - _save9 = self.pos - while true # sequence + _save8 = self.pos + begin # sequence _tmp = match_string("@<") - unless _tmp - self.pos = _save9 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save9 - break - end + break unless _tmp _tmp = apply(:_expression) o = @result - unless _tmp - self.pos = _save9 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save9 - break - end + break unless _tmp _tmp = match_string(">") - unless _tmp - self.pos = _save9 - break - end - @result = begin; @g.bounds(o) ; end + break unless _tmp + @result = begin; @g.bounds(o); end _tmp = true - unless _tmp - self.pos = _save9 - end - break + end while false + unless _tmp + self.pos = _save8 end # end sequence break if _tmp - self.pos = _save - _save10 = self.pos - while true # sequence + _save9 = self.pos + begin # sequence _tmp = match_string("<") - unless _tmp - self.pos = _save10 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save10 - break - end + break unless _tmp _tmp = apply(:_expression) o = @result - unless _tmp - self.pos = _save10 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save10 - break - end + break unless _tmp _tmp = match_string(">") - unless _tmp - self.pos = _save10 - break - end - @result = begin; @g.collect(o) ; end + break unless _tmp + @result = begin; @g.collect(o); end _tmp = true - unless _tmp - self.pos = _save10 - end - break + end while false + unless _tmp + self.pos = _save9 end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_curly_block) break if _tmp - self.pos = _save - _save11 = self.pos - while true # sequence + _save10 = self.pos + begin # sequence _tmp = match_string("~") - unless _tmp - self.pos = _save11 - break - end + break unless _tmp _tmp = apply(:_method) m = @result - unless _tmp - self.pos = _save11 - break - end + break unless _tmp _text_start = self.pos - _save12 = self.pos + # optional _tmp = apply(:_nested_paren) - unless _tmp - _tmp = true - self.pos = _save12 - end + _tmp = true # end optional if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save11 - break - end - @result = begin; @g.action("#{m}#{text}") ; end + break unless _tmp + @result = begin; @g.action("#{m}#{text}"); end _tmp = true - unless _tmp - self.pos = _save11 - end - break + end while false + unless _tmp + self.pos = _save10 end # end sequence break if _tmp - self.pos = _save - _save13 = self.pos - while true # sequence + _save11 = self.pos + begin # sequence _tmp = match_string(".") - unless _tmp - self.pos = _save13 - break - end - @result = begin; @g.dot ; end + break unless _tmp + @result = begin; @g.dot; end _tmp = true - unless _tmp - self.pos = _save13 - end - break + end while false + unless _tmp + self.pos = _save11 end # end sequence break if _tmp - self.pos = _save - _save14 = self.pos - while true # sequence + _save12 = self.pos + begin # sequence _tmp = match_string("@") - unless _tmp - self.pos = _save14 - break - end + break unless _tmp _tmp = apply(:_var) name = @result - unless _tmp - self.pos = _save14 - break - end + break unless _tmp _text_start = self.pos - _save15 = self.pos + # optional _tmp = apply(:_nested_paren) - unless _tmp - _tmp = true - self.pos = _save15 - end + _tmp = true # end optional if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save14 - break - end - _save16 = self.pos + break unless _tmp + _save13 = self.pos - _save17 = self.pos - while true # sequence + _save14 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save17 - break - end + break unless _tmp _tmp = match_string("=") - unless _tmp - self.pos = _save17 - end - break - end # end sequence - - _tmp = _tmp ? nil : true - self.pos = _save16 + end while false unless _tmp self.pos = _save14 - break - end - @result = begin; @g.invoke(name, text.empty? ? nil : text) ; end + end # end sequence + + _tmp = !_tmp + self.pos = _save13 + break unless _tmp + @result = begin; @g.invoke(name, text.empty? ? nil : text); end _tmp = true - unless _tmp - self.pos = _save14 - end - break + end while false + unless _tmp + self.pos = _save12 end # end sequence break if _tmp - self.pos = _save - _save18 = self.pos - while true # sequence + _save15 = self.pos + begin # sequence _tmp = match_string("^") - unless _tmp - self.pos = _save18 - break - end + break unless _tmp _tmp = apply(:_var) name = @result - unless _tmp - self.pos = _save18 - break - end + break unless _tmp _text_start = self.pos - _save19 = self.pos + # optional _tmp = apply(:_nested_paren) - unless _tmp - _tmp = true - self.pos = _save19 - end + _tmp = true # end optional if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save18 - break - end - @result = begin; @g.foreign_invoke("parent", name, text) ; end + break unless _tmp + @result = begin; @g.foreign_invoke("parent", name, text); end _tmp = true - unless _tmp - self.pos = _save18 - end - break + end while false + unless _tmp + self.pos = _save15 end # end sequence break if _tmp - self.pos = _save - _save20 = self.pos - while true # sequence + _save16 = self.pos + begin # sequence _tmp = match_string("%") - unless _tmp - self.pos = _save20 - break - end + break unless _tmp _tmp = apply(:_var) gram = @result - unless _tmp - self.pos = _save20 - break - end + break unless _tmp _tmp = match_string(".") - unless _tmp - self.pos = _save20 - break - end + break unless _tmp _tmp = apply(:_var) name = @result - unless _tmp - self.pos = _save20 - break - end + break unless _tmp _text_start = self.pos - _save21 = self.pos + # optional _tmp = apply(:_nested_paren) - unless _tmp - _tmp = true - self.pos = _save21 - end + _tmp = true # end optional if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save20 - break - end - @result = begin; @g.foreign_invoke(gram, name, text) ; end + break unless _tmp + @result = begin; @g.foreign_invoke(gram, name, text); end _tmp = true - unless _tmp - self.pos = _save20 - end - break + end while false + unless _tmp + self.pos = _save16 end # end sequence break if _tmp - self.pos = _save - _save22 = self.pos - while true # sequence + _save17 = self.pos + begin # sequence _tmp = apply(:_var) name = @result - unless _tmp - self.pos = _save22 - break - end + break unless _tmp _text_start = self.pos - _save23 = self.pos + # optional _tmp = apply(:_nested_paren) - unless _tmp - _tmp = true - self.pos = _save23 - end + _tmp = true # end optional if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save22 - break - end - _save24 = self.pos + break unless _tmp + _save18 = self.pos - _save25 = self.pos - while true # sequence + _save19 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save25 - break - end + break unless _tmp _tmp = match_string("=") - unless _tmp - self.pos = _save25 - end - break + end while false + unless _tmp + self.pos = _save19 end # end sequence - _tmp = _tmp ? nil : true - self.pos = _save24 - unless _tmp - self.pos = _save22 - break - end - @result = begin; @g.ref(name, nil, text.empty? ? nil : text) ; end + _tmp = !_tmp + self.pos = _save18 + break unless _tmp + @result = begin; @g.ref(name, nil, text.empty? ? nil : text); end _tmp = true - unless _tmp - self.pos = _save22 - end - break + end while false + unless _tmp + self.pos = _save17 end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_char_range) break if _tmp - self.pos = _save _tmp = apply(:_regexp) break if _tmp - self.pos = _save _tmp = apply(:_string) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_value unless _tmp return _tmp @@ -2231,39 +1695,23 @@ def _value # spaces = (space | comment)+ def _spaces - _save = self.pos - - _save1 = self.pos - while true # choice - _tmp = apply(:_space) - break if _tmp - self.pos = _save1 - _tmp = apply(:_comment) - break if _tmp - self.pos = _save1 - break - end # end choice - - if _tmp - while true + _save = self.pos # repetition + _count = 0 + while true - _save2 = self.pos - while true # choice - _tmp = apply(:_space) - break if _tmp - self.pos = _save2 - _tmp = apply(:_comment) - break if _tmp - self.pos = _save2 - break - end # end choice + begin # choice + _tmp = apply(:_space) + break if _tmp + _tmp = apply(:_comment) + end while false # end choice - break unless _tmp - end - _tmp = true - else - self.pos = _save + break unless _tmp + _count += 1 end + _tmp = _count >= 1 + unless _tmp + self.pos = _save + end # end repetition set_failed_rule :_spaces unless _tmp return _tmp end @@ -2271,73 +1719,47 @@ def _spaces # values = (values:s spaces value:v { @g.seq(s, v) } | value:l spaces value:r { @g.seq(l, r) } | value) def _values - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_values) s = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_spaces) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_value) v = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; @g.seq(s, v) ; end + break unless _tmp + @result = begin; @g.seq(s, v); end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_value) l = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_spaces) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_value) r = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; @g.seq(l, r) ; end + break unless _tmp + @result = begin; @g.seq(l, r); end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_value) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_values unless _tmp return _tmp @@ -2347,34 +1769,21 @@ def _values def _choose_cont _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("|") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:_values) v = @result - unless _tmp - self.pos = _save - break - end - @result = begin; v ; end + break unless _tmp + @result = begin; v; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_choose_cont unless _tmp @@ -2384,52 +1793,38 @@ def _choose_cont # expression = (values:v choose_cont+:alts { @g.any(v, *alts) } | values) def _expression - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_values) v = @result - unless _tmp - self.pos = _save1 - break - end - _save2 = self.pos + break unless _tmp + _save1 = self.pos # repetition _ary = [] - _tmp = apply(:_choose_cont) - if _tmp + while true + _tmp = apply(:_choose_cont) + break unless _tmp _ary << @result - while true - _tmp = apply(:_choose_cont) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save2 end - alts = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp self.pos = _save1 - break - end - @result = begin; @g.any(v, *alts) ; end + @result = nil + end # end repetition + alts = @result + break unless _tmp + @result = begin; @g.any(v, *alts); end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_values) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_expression unless _tmp return _tmp @@ -2438,79 +1833,48 @@ def _expression # args = (args:a "," - var:n - { a + [n] } | - var:n - { [n] }) def _args - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_args) a = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string(",") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_var) n = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end - @result = begin; a + [n] ; end + break unless _tmp + @result = begin; a + [n]; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_var) n = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end - @result = begin; [n] ; end + break unless _tmp + @result = begin; [n]; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_args unless _tmp return _tmp @@ -2519,350 +1883,194 @@ def _args # statement = (- var:v "(" args:a ")" - "=" - expression:o { @g.set(v, o, a) } | - var:v - "=" - expression:o { @g.set(v, o) } | - "%" var:name - "=" - < /[:\w]+/ > { @g.add_foreign_grammar(name, text) } | - "%%" - curly:act { @g.add_setup act } | - "%%" - var:name - curly:act { @g.add_directive name, act } | - "%%" - var:name - "=" - < (!"\n" .)+ > { @g.set_variable(name, text) }) def _statement - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_var) v = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string("(") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_args) a = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string(")") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string("=") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_expression) o = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; @g.set(v, o, a) ; end + break unless _tmp + @result = begin; @g.set(v, o, a); end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_var) v = @result - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = match_string("=") - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_expression) o = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; @g.set(v, o) ; end + break unless _tmp + @result = begin; @g.set(v, o); end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save - _save3 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = match_string("%") - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = apply(:_var) name = @result - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save3 - break - end + break unless _tmp _tmp = match_string("=") - unless _tmp - self.pos = _save3 - break - end - _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save3 - break - end + break unless _tmp + _tmp = apply(:__hyphen_) + break unless _tmp _text_start = self.pos _tmp = scan(/\G(?-mix:[:\w]+)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save3 - break - end - @result = begin; @g.add_foreign_grammar(name, text) ; end + break unless _tmp + @result = begin; @g.add_foreign_grammar(name, text); end _tmp = true - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save2 end # end sequence break if _tmp - self.pos = _save - _save4 = self.pos - while true # sequence + _save3 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save4 - break - end + break unless _tmp _tmp = match_string("%%") - unless _tmp - self.pos = _save4 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save4 - break - end + break unless _tmp _tmp = apply(:_curly) act = @result - unless _tmp - self.pos = _save4 - break - end - @result = begin; @g.add_setup act ; end + break unless _tmp + @result = begin; @g.add_setup act; end _tmp = true - unless _tmp - self.pos = _save4 - end - break + end while false + unless _tmp + self.pos = _save3 end # end sequence break if _tmp - self.pos = _save - _save5 = self.pos - while true # sequence + _save4 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = match_string("%%") - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:_var) name = @result - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save5 - break - end + break unless _tmp _tmp = apply(:_curly) act = @result - unless _tmp - self.pos = _save5 - break - end - @result = begin; @g.add_directive name, act ; end + break unless _tmp + @result = begin; @g.add_directive name, act; end _tmp = true - unless _tmp - self.pos = _save5 - end - break + end while false + unless _tmp + self.pos = _save4 end # end sequence break if _tmp - self.pos = _save - _save6 = self.pos - while true # sequence + _save5 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _tmp = match_string("%%") - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _tmp = apply(:_var) name = @result - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _tmp = match_string("=") - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save6 - break - end + break unless _tmp _text_start = self.pos - _save7 = self.pos - - _save8 = self.pos - while true # sequence - _save9 = self.pos - _tmp = match_string("\n") - _tmp = _tmp ? nil : true - self.pos = _save9 - unless _tmp + _save6 = self.pos # repetition + _count = 0 + while true + + _save7 = self.pos + begin # sequence + _save8 = self.pos + _tmp = match_string("\n") + _tmp = !_tmp self.pos = _save8 - break - end - _tmp = get_byte + break unless _tmp + _tmp = match_dot + end while false unless _tmp - self.pos = _save8 - end - break - end # end sequence - - if _tmp - while true - - _save10 = self.pos - while true # sequence - _save11 = self.pos - _tmp = match_string("\n") - _tmp = _tmp ? nil : true - self.pos = _save11 - unless _tmp - self.pos = _save10 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save10 - end - break - end # end sequence + self.pos = _save7 + end # end sequence - break unless _tmp - end - _tmp = true - else - self.pos = _save7 - end - if _tmp - text = get_text(_text_start) + break unless _tmp + _count += 1 end + _tmp = _count >= 1 unless _tmp self.pos = _save6 - break + end # end repetition + if _tmp + text = get_text(_text_start) end - @result = begin; @g.set_variable(name, text) ; end + break unless _tmp + @result = begin; @g.set_variable(name, text); end _tmp = true - unless _tmp - self.pos = _save6 - end - break + end while false + unless _tmp + self.pos = _save5 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_statement unless _tmp return _tmp @@ -2872,36 +2080,25 @@ def _statement def _statements _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_statement) - unless _tmp - self.pos = _save - break - end - _save1 = self.pos + break unless _tmp + # optional - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save2 - break - end + break unless _tmp _tmp = apply(:_statements) - unless _tmp - self.pos = _save2 - end - break - end # end sequence - + end while false unless _tmp - _tmp = true self.pos = _save1 - end - unless _tmp - self.pos = _save - end - break + end # end sequence + + _tmp = true # end optional + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_statements unless _tmp @@ -2911,8 +2108,8 @@ def _statements # eof = !. def _eof _save = self.pos - _tmp = get_byte - _tmp = _tmp ? nil : true + _tmp = match_dot + _tmp = !_tmp self.pos = _save set_failed_rule :_eof unless _tmp return _tmp @@ -2922,32 +2119,19 @@ def _eof def _root _save = self.pos - while true # sequence + begin # sequence _tmp = apply(:_statements) - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = apply(:__hyphen_) - unless _tmp - self.pos = _save - break - end - _save1 = self.pos + break unless _tmp + # optional _tmp = apply(:_eof_comment) - unless _tmp - _tmp = true - self.pos = _save1 - end - unless _tmp - self.pos = _save - break - end + _tmp = true # end optional + break unless _tmp _tmp = apply(:_eof) - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -2958,22 +2142,18 @@ def _root def _ast_constant _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[A-Z]\w*)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_ast_constant unless _tmp @@ -2984,22 +2164,18 @@ def _ast_constant def _ast_word _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = scan(/\G(?i-mx:[a-z_]\w*)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_ast_word unless _tmp @@ -3008,22 +2184,17 @@ def _ast_word # ast_sp = (" " | "\t")* def _ast_sp - while true + while true # kleene - _save1 = self.pos - while true # choice + begin # choice _tmp = match_string(" ") break if _tmp - self.pos = _save1 _tmp = match_string("\t") - break if _tmp - self.pos = _save1 - break - end # end choice + end while false # end choice break unless _tmp end - _tmp = true + _tmp = true # end kleene set_failed_rule :_ast_sp unless _tmp return _tmp end @@ -3031,69 +2202,44 @@ def _ast_sp # ast_words = (ast_words:r ast_sp "," ast_sp ast_word:w { r + [w] } | ast_word:w { [w] }) def _ast_words - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_ast_words) r = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_ast_sp) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string(",") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_ast_sp) - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_ast_word) w = @result - unless _tmp - self.pos = _save1 - break - end - @result = begin; r + [w] ; end + break unless _tmp + @result = begin; r + [w]; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_ast_word) w = @result - unless _tmp - self.pos = _save2 - break - end - @result = begin; [w] ; end + break unless _tmp + @result = begin; [w]; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_ast_words unless _tmp return _tmp @@ -3102,74 +2248,46 @@ def _ast_words # ast_root = (ast_constant:c "(" ast_words:w ")" { [c, w] } | ast_constant:c "()"? { [c, []] }) def _ast_root - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = apply(:_ast_constant) c = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string("(") - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = apply(:_ast_words) w = @result - unless _tmp - self.pos = _save1 - break - end + break unless _tmp _tmp = match_string(")") - unless _tmp - self.pos = _save1 - break - end - @result = begin; [c, w] ; end + break unless _tmp + @result = begin; [c, w]; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = apply(:_ast_constant) c = @result - unless _tmp - self.pos = _save2 - break - end - _save3 = self.pos + break unless _tmp + # optional _tmp = match_string("()") - unless _tmp - _tmp = true - self.pos = _save3 - end - unless _tmp - self.pos = _save2 - break - end - @result = begin; [c, []] ; end + _tmp = true # end optional + break unless _tmp + @result = begin; [c, []]; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_ast_root unless _tmp return _tmp diff --git a/lib/kpeg/string_escape.rb b/lib/kpeg/string_escape.rb index 31f34fc..d4b43e8 100644 --- a/lib/kpeg/string_escape.rb +++ b/lib/kpeg/string_escape.rb @@ -197,6 +197,15 @@ def set_failed_rule(name) attr_reader :failed_rule + def match_dot() + if @pos >= @string_size + return nil + end + + @pos += 1 + true + end + def match_string(str) len = str.size if @string[pos,len] == str @@ -217,24 +226,26 @@ def scan(reg) end if "".respond_to? :ord - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos].ord) + return nil end - s = @string[@pos].ord @pos += 1 - s + true end else - def get_byte + def match_char_range(char_range) if @pos >= @string_size return nil + elsif !char_range.include?(@string[@pos]) + return nil end - s = @string[@pos] @pos += 1 - s + true end end @@ -407,162 +418,119 @@ def setup_foreign_grammar; end # segment = (< /[\w ]+/ > { text } | "\\" { "\\\\" } | "\n" { "\\n" } | "\r" { "\\r" } | "\t" { "\\t" } | "\b" { "\\b" } | "\"" { "\\\"" } | < . > { text }) def _segment - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _text_start = self.pos _tmp = scan(/\G(?-mix:[\w ]+)/) if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save1 - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save - _save2 = self.pos - while true # sequence + _save1 = self.pos + begin # sequence _tmp = match_string("\\") - unless _tmp - self.pos = _save2 - break - end - @result = begin; "\\\\" ; end + break unless _tmp + @result = begin; "\\\\"; end _tmp = true - unless _tmp - self.pos = _save2 - end - break + end while false + unless _tmp + self.pos = _save1 end # end sequence break if _tmp - self.pos = _save - _save3 = self.pos - while true # sequence + _save2 = self.pos + begin # sequence _tmp = match_string("\n") - unless _tmp - self.pos = _save3 - break - end - @result = begin; "\\n" ; end + break unless _tmp + @result = begin; "\\n"; end _tmp = true - unless _tmp - self.pos = _save3 - end - break + end while false + unless _tmp + self.pos = _save2 end # end sequence break if _tmp - self.pos = _save - _save4 = self.pos - while true # sequence + _save3 = self.pos + begin # sequence _tmp = match_string("\r") - unless _tmp - self.pos = _save4 - break - end - @result = begin; "\\r" ; end + break unless _tmp + @result = begin; "\\r"; end _tmp = true - unless _tmp - self.pos = _save4 - end - break + end while false + unless _tmp + self.pos = _save3 end # end sequence break if _tmp - self.pos = _save - _save5 = self.pos - while true # sequence + _save4 = self.pos + begin # sequence _tmp = match_string("\t") - unless _tmp - self.pos = _save5 - break - end - @result = begin; "\\t" ; end + break unless _tmp + @result = begin; "\\t"; end _tmp = true - unless _tmp - self.pos = _save5 - end - break + end while false + unless _tmp + self.pos = _save4 end # end sequence break if _tmp - self.pos = _save - _save6 = self.pos - while true # sequence + _save5 = self.pos + begin # sequence _tmp = match_string("\b") - unless _tmp - self.pos = _save6 - break - end - @result = begin; "\\b" ; end + break unless _tmp + @result = begin; "\\b"; end _tmp = true - unless _tmp - self.pos = _save6 - end - break + end while false + unless _tmp + self.pos = _save5 end # end sequence break if _tmp - self.pos = _save - _save7 = self.pos - while true # sequence + _save6 = self.pos + begin # sequence _tmp = match_string("\"") - unless _tmp - self.pos = _save7 - break - end - @result = begin; "\\\"" ; end + break unless _tmp + @result = begin; "\\\""; end _tmp = true - unless _tmp - self.pos = _save7 - end - break + end while false + unless _tmp + self.pos = _save6 end # end sequence break if _tmp - self.pos = _save - _save8 = self.pos - while true # sequence + _save7 = self.pos + begin # sequence _text_start = self.pos - _tmp = get_byte + _tmp = match_dot if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save8 - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save8 - end - break + end while false + unless _tmp + self.pos = _save7 end # end sequence - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_segment unless _tmp return _tmp @@ -572,26 +540,22 @@ def _segment def _root _save = self.pos - while true # sequence - _ary = [] + begin # sequence + _ary = [] # kleene while true _tmp = apply(:_segment) - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene s = @result - unless _tmp - self.pos = _save - break - end - @result = begin; @text = s.join ; end + break unless _tmp + @result = begin; @text = s.join; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -601,31 +565,22 @@ def _root # embed_seg = ("#" { "\\#" } | segment) def _embed_seg - _save = self.pos - while true # choice + begin # choice - _save1 = self.pos - while true # sequence + _save = self.pos + begin # sequence _tmp = match_string("#") - unless _tmp - self.pos = _save1 - break - end - @result = begin; "\\#" ; end + break unless _tmp + @result = begin; "\\#"; end _tmp = true - unless _tmp - self.pos = _save1 - end - break + end while false + unless _tmp + self.pos = _save end # end sequence break if _tmp - self.pos = _save _tmp = apply(:_segment) - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_embed_seg unless _tmp return _tmp @@ -635,26 +590,22 @@ def _embed_seg def _embed _save = self.pos - while true # sequence - _ary = [] + begin # sequence + _ary = [] # kleene while true _tmp = apply(:_embed_seg) - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene s = @result - unless _tmp - self.pos = _save - break - end - @result = begin; @text = s.join ; end + break unless _tmp + @result = begin; @text = s.join; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_embed unless _tmp diff --git a/test/test_kpeg_code_generator.rb b/test/test_kpeg_code_generator.rb index 9cc46f6..a73ccb5 100644 --- a/test/test_kpeg_code_generator.rb +++ b/test/test_kpeg_code_generator.rb @@ -18,7 +18,7 @@ class Test < KPeg::CompiledParser # root = . def _root - _tmp = get_byte + _tmp = match_dot set_failed_rule :_root unless _tmp return _tmp end @@ -165,14 +165,7 @@ class Test < KPeg::CompiledParser # root = [a-z] def _root - _save = self.pos - _tmp = get_byte - if _tmp - unless _tmp >= 97 and _tmp <= 122 - self.pos = _save - _tmp = nil - end - end + _tmp = match_char_range(97..122) set_failed_rule :_root unless _tmp return _tmp end @@ -207,24 +200,13 @@ class Test < KPeg::CompiledParser def _root _save = self.pos - while true # sequence - _save1 = self.pos - _tmp = get_byte - if _tmp - unless _tmp >= 97 and _tmp <= 122 - self.pos = _save1 - _tmp = nil - end - end - unless _tmp - self.pos = _save - break - end + begin # sequence + _tmp = match_char_range(97..122) + break unless _tmp _tmp = match_string("hello") - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -261,16 +243,11 @@ class Test < KPeg::CompiledParser # root = ("hello" | "world") def _root - _save = self.pos - while true # choice + begin # choice _tmp = match_string("hello") break if _tmp - self.pos = _save _tmp = match_string("world") - break if _tmp - self.pos = _save - break - end # end choice + end while false # end choice set_failed_rule :_root unless _tmp return _tmp @@ -318,12 +295,9 @@ class Test < KPeg::CompiledParser # root = "hello"? def _root - _save = self.pos + # optional _tmp = match_string("hello") - unless _tmp - _tmp = true - self.pos = _save - end + _tmp = true # end optional set_failed_rule :_root unless _tmp return _tmp end @@ -369,11 +343,11 @@ class Test < KPeg::CompiledParser # root = "hello"* def _root - while true + while true # kleene _tmp = match_string("hello") break unless _tmp end - _tmp = true + _tmp = true # end kleene set_failed_rule :_root unless _tmp return _tmp end @@ -422,17 +396,17 @@ class Test < KPeg::CompiledParser # root = "hello"+ def _root - _save = self.pos - _tmp = match_string("hello") - if _tmp - while true - _tmp = match_string("hello") - break unless _tmp - end - _tmp = true - else - self.pos = _save + _save = self.pos # repetition + _count = 0 + while true + _tmp = match_string("hello") + break unless _tmp + _count += 1 end + _tmp = _count >= 1 + unless _tmp + self.pos = _save + end # end repetition set_failed_rule :_root unless _tmp return _tmp end @@ -488,23 +462,18 @@ class Test < KPeg::CompiledParser # root = "hello"[5, 9] def _root - _save = self.pos + _save = self.pos # repetition _count = 0 while true _tmp = match_string("hello") - if _tmp - _count += 1 - break if _count == 9 - else - break - end + break unless _tmp + _count += 1 + break if _count == 9 end - if _count >= 5 - _tmp = true - else + _tmp = _count >= 5 + unless _tmp self.pos = _save - _tmp = nil - end + end # end repetition set_failed_rule :_root unless _tmp return _tmp end @@ -535,17 +504,13 @@ class Test < KPeg::CompiledParser def _root _save = self.pos - while true # sequence + begin # sequence _tmp = match_string("hello") - unless _tmp - self.pos = _save - break - end + break unless _tmp _tmp = match_string("world") - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -631,7 +596,7 @@ class Test < KPeg::CompiledParser # root = &{ !defined? @fail } def _root _save = self.pos - _tmp = begin; !defined? @fail ; end + _tmp = begin; !defined? @fail; end self.pos = _save set_failed_rule :_root unless _tmp return _tmp @@ -672,7 +637,7 @@ class Test < KPeg::CompiledParser def _root _save = self.pos _tmp = match_string("hello") - _tmp = _tmp ? nil : true + _tmp = !_tmp self.pos = _save set_failed_rule :_root unless _tmp return _tmp @@ -711,8 +676,8 @@ class Test < KPeg::CompiledParser # root = !{ defined? @fail } def _root _save = self.pos - _tmp = begin; defined? @fail ; end - _tmp = _tmp ? nil : true + _tmp = begin; defined? @fail; end + _tmp = !_tmp self.pos = _save set_failed_rule :_root unless _tmp return _tmp @@ -1011,22 +976,18 @@ class Test < KPeg::CompiledParser def _hello _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = match_string("hello") if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_hello unless _tmp @@ -1037,25 +998,18 @@ def _hello def _root _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + # optional _tmp = apply(:_hello) @result = nil unless _tmp - unless _tmp - _tmp = true - self.pos = _save1 - end + _tmp = true # end optional lots = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; lots; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -1099,22 +1053,18 @@ class Test < KPeg::CompiledParser def _hello _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = match_string("hello") if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_hello unless _tmp @@ -1125,26 +1075,22 @@ def _hello def _root _save = self.pos - while true # sequence - _ary = [] + begin # sequence + _ary = [] # kleene while true _tmp = apply(:_hello) - _ary << @result if _tmp break unless _tmp + _ary << @result end - _tmp = true @result = _ary + _tmp = true # end kleene lots = @result - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; lots; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -1191,22 +1137,18 @@ class Test < KPeg::CompiledParser def _hello _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = match_string("hello") if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end + break unless _tmp @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_hello unless _tmp @@ -1217,33 +1159,27 @@ def _hello def _root _save = self.pos - while true # sequence - _save1 = self.pos + begin # sequence + _save1 = self.pos # repetition _ary = [] - _tmp = apply(:_hello) - if _tmp + while true + _tmp = apply(:_hello) + break unless _tmp _ary << @result - while true - _tmp = apply(:_hello) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 end - lots = @result + @result = _ary + _tmp = _ary.size >= 1 unless _tmp - self.pos = _save - break - end + self.pos = _save1 + @result = nil + end # end repetition + lots = @result + break unless _tmp @result = begin; lots; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -1322,22 +1258,18 @@ class Test < KPeg::CompiledParser def _root _save = self.pos - while true # sequence + begin # sequence _text_start = self.pos _tmp = match_string("hello") if _tmp text = get_text(_text_start) end - unless _tmp - self.pos = _save - break - end - @result = begin; text ; end + break unless _tmp + @result = begin; text; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -1374,22 +1306,18 @@ class Test < KPeg::CompiledParser def _root _save = self.pos - while true # sequence + begin # sequence _bounds_start = self.pos _tmp = match_string("hello") if _tmp bounds = [_bounds_start, self.pos] end - unless _tmp - self.pos = _save - break - end - @result = begin; bounds ; end + break unless _tmp + @result = begin; bounds; end _tmp = true - unless _tmp - self.pos = _save - end - break + end while false + unless _tmp + self.pos = _save end # end sequence set_failed_rule :_root unless _tmp @@ -1466,7 +1394,7 @@ class Test < KPeg::CompiledParser # root = . def _root - _tmp = get_byte + _tmp = match_dot set_failed_rule :_root unless _tmp return _tmp end @@ -1501,7 +1429,7 @@ class Test < KPeg::CompiledParser # root = . def _root - _tmp = get_byte + _tmp = match_dot set_failed_rule :_root unless _tmp return _tmp end @@ -1534,7 +1462,7 @@ class Test < KPeg::CompiledParser # root = . def _root - _tmp = get_byte + _tmp = match_dot set_failed_rule :_root unless _tmp return _tmp end @@ -1581,7 +1509,7 @@ class Test < KPeg::CompiledParser # root = . def _root - _tmp = get_byte + _tmp = match_dot set_failed_rule :_root unless _tmp return _tmp end @@ -1676,7 +1604,7 @@ def simple2() # root = . def _root - _tmp = get_byte + _tmp = match_dot set_failed_rule :_root unless _tmp return _tmp end @@ -1727,7 +1655,7 @@ def bracket(receiver, argument) # root = . def _root - _tmp = get_byte + _tmp = match_dot set_failed_rule :_root unless _tmp return _tmp end