lib/dentaku/tokenizer.rb in dentaku-2.0.11 vs lib/dentaku/tokenizer.rb in dentaku-3.0.0

- old
+ new

@@ -11,17 +11,21 @@ @nesting = 0 @tokens = [] input = strip_comments(string.to_s.dup) until input.empty? - fail TokenizerError, "parse error at: '#{ input }'" unless TokenScanner.scanners.any? do |scanner| + scanned = TokenScanner.scanners.any? do |scanner| scanned, input = scan(input, scanner) scanned end + + unless scanned + fail! :parse_error, at: input + end end - fail TokenizerError, "too many opening parentheses" if @nesting > 0 + fail! :too_many_opening_parentheses if @nesting > 0 @tokens end def last_token @@ -29,15 +33,18 @@ end def scan(string, scanner) if tokens = scanner.scan(string, last_token) tokens.each do |token| - fail TokenizerError, "unexpected zero-width match (:#{ token.category }) at '#{ string }'" if token.length == 0 + if token.empty? + fail! :unexpected_zero_width_match, + token_category: token.category, at: string + end @nesting += 1 if LPAREN == token @nesting -= 1 if RPAREN == token - fail TokenizerError, "too many closing parentheses" if @nesting < 0 + fail! :too_many_closing_parentheses if @nesting < 0 @tokens << token unless token.is?(:whitespace) end match_length = tokens.map(&:length).reduce(:+) @@ -47,8 +54,28 @@ end end def strip_comments(input) input.gsub(/\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//, '') + end + + private + + def fail!(reason, **meta) + message = + case reason + when :parse_error + "parse error at: '#{meta.fetch(:at)}'" + when :too_many_opening_parentheses + "too many opening parentheses" + when :too_many_closing_parentheses + "too many closing parentheses" + when :unexpected_zero_width_match + "unexpected zero-width match (:#{meta.fetch(:category)}) at '#{meta.fetch(:at)}'" + else + raise ::ArgumentError, "Unhandled #{reason}" + end + + raise TokenizerError.for(reason, meta), message end end end