class ComponentEmbeddedRuby::Lexer

Constants

Position
Token

Attributes

reader[R]

Public Class Methods

new(content) click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 12
def initialize(content)
  @reader = InputReader.new(content)

  @tokens = []
end

Public Instance Methods

lex() click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 18
def lex # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
  while !reader.eof?
    char = reader.current_char

    if char == "<"
      add_token(:open_carrot, "<")
      reader.next
    elsif char == ">"
      add_token(:close_carrot, ">")
      reader.next
    elsif char == "="
      add_token(:equals, "=")
      reader.next
    elsif char == '"'
      add_token(:string, read_quoted_string)
    elsif char == "/"
      add_token(:slash, "/")
      reader.next
    elsif char == "{"
      if reader.peek == "-"
        reader.next
        add_token(:ruby_no_eval, read_ruby_string)
      else
        add_token(:ruby, read_ruby_string)
      end
    elsif letter?(char)
      position = Position.new(reader.current_line, reader.current_column)

      if @tokens[-1]&.type == :close_carrot
        add_token(:string, read_body_string, position)
      else
        add_token(:identifier, read_string, position)
      end
    else
      reader.next
    end
  end

  @tokens
end

Private Instance Methods

add_token(type, value, position = Position.new(reader.current_line, reader.current_column)) click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 63
def add_token(type, value, position = Position.new(reader.current_line, reader.current_column))
  token = Token.new(type, value, position)
  @tokens << token
end
letter?(char) click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 119
def letter?(char)
  ascii = char.ord
  (ascii >= 48 && ascii <= 57) || (ascii >= 65 && ascii <= 122) || ascii == 45 || ascii == 95 || ascii == 58
end
read_body_string() click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 98
def read_body_string
  string = ""

  while reader.current_char != "<" && reader.current_char != "{"
    raise "unterminated content" if reader.eof?

    string += reader.current_char
    reader.next
  end

  string
end
read_quoted_string() click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 79
def read_quoted_string
  string = ""

  # Get past initial "
  reader.next

  while !unescaped_quote?
    raise "unterminated string" if reader.eof?

    string += reader.current_char
    reader.next
  end

  # Get past last "
  reader.next

  string
end
read_ruby_string() click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 111
def read_ruby_string
  RubyCodeReader.new(reader).read_until_closing_tag
end
read_string() click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 68
def read_string
  string = ""

  while letter?(reader.current_char) && !reader.eof?
    string += reader.current_char
    reader.next
  end

  string
end
unescaped_quote?() click to toggle source
# File lib/component_embedded_ruby/lexer.rb, line 115
def unescaped_quote?
  reader.current_char == '"' && reader.peek_behind != '\\'
end