examples/tokenizer/loxxy_tokenizer.rb in rley-0.8.05 vs examples/tokenizer/loxxy_tokenizer.rb in rley-0.8.06
- old
+ new
@@ -1,26 +1,37 @@
# frozen_string_literal: true
require 'rley'
require_relative 'loxxy_raw_scanner.rex'
+# Tokenizer for the Lox language that is compatible with a Rley parser.
+# It works as an adapter between the parser and the scanner generated
+# with `oedipus_lex` scanner generator.
+# The purpose is to transform the output of a `LoxxyRawScanner` instance
+# into o sequence of tokens in the format expected by Rley.
class LoxxyTokenizer
# @return [LoxxyRawScanner] Scanner generated by `oedipus_lex`gem.
attr_reader :scanner
- # @return [String] Input text to tokenize
+ # @return [String] Lox input text to tokenize
attr_reader :input
+ # A Hash that maps a Lox keyword to its uppercase version
+ # (a convention used in the grammar).
+ # If a search is unsuccessful, it returns the string 'IDENTIFIER'
+ # @return [{String => String}]
Keyword2name = begin
lookup = %w[
and class else false fun for if nil or
print return super this true var while
].map { |x| [x, x.upcase] }.to_h
lookup.default = 'IDENTIFIER'
lookup.freeze
end
+ # A Hash that maps a special character of Lox into a name
+ # @return [{String => String}]
Special2name = {
'(' => 'LEFT_PAREN',
')' => 'RIGHT_PAREN',
'{' => 'LEFT_BRACE',
'}' => 'RIGHT_BRACE',
@@ -39,19 +50,26 @@
'>=' => 'GREATER_EQUAL',
'<' => 'LESS',
'<=' => 'LESS_EQUAL'
}.freeze
+ # Constructor
+ # @param source [String, NilClass] Optional. The text to tokenize
def initialize(source = nil)
@scanner = LoxxyRawScanner.new
start_with(source)
end
+ # Set the text to tokenize.
+ # @param source [String] The text to tokenize
def start_with(source)
@input = source
end
+ # Launch the scanning/tokenization of input text.
+ # Returns an array of Rley token objects.
+ # @return [Array<Rley::Lexical::Token>] array of token objects.
def tokens
raw_tokens = scanner.parse(input)
cooked = raw_tokens.map do |(raw_type, raw_text, line, col)|
pos = Rley::Lexical::Position.new(line, col + 1)
convert(raw_type, raw_text, pos)
@@ -63,9 +81,10 @@
cooked
end
private
+ # Convert the raw tokens from generated scanner into something edible by Rley.
def convert(token_kind, token_text, pos)
result = case token_kind
when :SPECIAL
Rley::Lexical::Token.new(token_text, Special2name[token_text])
when :FALSE