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