lib/jkf/parser/base.rb in jkf-0.5.0 vs lib/jkf/parser/base.rb in jkf-0.5.1
- old
+ new
@@ -1,118 +1,104 @@
-module Jkf::Parser
- # Base of Parser
- class Base
- # start parse
- #
- # @param [String] input
- #
- # @return [Hash] JKF
- def parse(input)
- @input = input.clone
+require 'strscan'
- @current_pos = 0
- @reported_pos = 0
- @cached_pos = 0
- @cached_pos_details = { line: 1, column: 1, seenCR: false }
- @max_fail_pos = 0
- @max_fail_expected = []
- @silent_fails = 0
+module Jkf
+ module Parser
+ # Base of Parser
+ class Base
+ # start parse
+ #
+ # @param [String] input
+ #
+ # @return [Hash] JKF
+ def parse(input)
+ @scanner = StringScanner.new(input.dup)
+ @reported_pos = 0
+ @max_fail_pos = 0
- @result = parse_root
+ @result = parse_root
- if success? && @current_pos == @input.size
- return @result
- else
- fail(type: "end", description: "end of input") if failed? && @current_pos < input.size
- raise ParseError
+ if success? && @scanner.eos?
+ @result
+ else
+ record_failure(type: 'end', description: 'end of input') if failed? && @scanner.pos < input.size
+ raise ParseError
+ end
end
- end
- protected
+ protected
- def success?
- @result != :failed
- end
+ def success?
+ @result != :failed
+ end
- def failed?; !success?; end
+ def failed?; !success?; end
- # match regexp
- def match_regexp(reg)
- ret = nil
- if matched = reg.match(@input[@current_pos])
- ret = matched.to_s
- @current_pos += ret.size
- else
- ret = :failed
- fail(type: "class", value: reg.inspect, description: reg.inspect) if @silent_fails == 0
+ def match_regexp(reg)
+ matched = @scanner.scan(reg)
+ unless matched
+ record_failure(type: 'class', value: reg.inspect, description: reg.inspect)
+ return :failed
+ end
+ matched
end
- ret
- end
- # match string
- def match_str(str)
- ret = nil
- if @input[@current_pos, str.size] == str
- ret = str
- @current_pos += str.size
- else
- ret = :failed
- fail(type: "literal", value: str, description: "\"#{str}\"") if @slient_fails == 0
+ def match_str(str)
+ matched = @scanner.scan(str)
+ unless matched
+ record_failure(type: 'literal', value: str, description: str.inspect)
+ return :failed
+ end
+ matched
end
- ret
- end
- # match space
- def match_space
- match_str(" ")
- end
+ # match space
+ def match_space
+ match_str(' ')
+ end
- # match space one or more
- def match_spaces
- stack = []
- matched = match_space
- while matched != :failed
- stack << matched
+ # match space one or more
+ def match_spaces
+ stack = []
matched = match_space
+ while matched != :failed
+ stack << matched
+ matched = match_space
+ end
+ stack
end
- stack
- end
- # match digit
- def match_digit
- match_regexp(/^\d/)
- end
+ # match digit
+ def match_digit
+ match_regexp(/\d/)
+ end
- # match digits
- def match_digits
- stack = []
- matched = match_digit
- while matched != :failed
- stack << matched
+ # match digits
+ def match_digits
+ stack = []
matched = match_digit
+ while matched != :failed
+ stack << matched
+ matched = match_digit
+ end
+ stack
end
- stack
- end
- # match digit one ore more
- def match_digits!
- matched = match_digits
- if matched.empty?
- :failed
- else
- matched
+ # match digit one ore more
+ def match_digits!
+ matched = match_digits
+ if matched.empty?
+ :failed
+ else
+ matched
+ end
end
- end
- # record failure
- def fail(expected)
- return if @current_pos < @max_fail_pos
+ def record_failure(expected)
+ return if @scanner.pos < @max_fail_pos
- if @current_pos > @max_fail_pos
- @max_fail_pos = @current_pos
- @max_fail_expected = []
- end
+ return unless @scanner.pos > @max_fail_pos
- @max_fail_expected << expected
+ @max_fail_pos = @scanner.pos
+ end
end
end
end