class Rubic::Lexer
Constants
- EOT
- KEYWORD_TABLE
- SYM_CHARS
Public Class Methods
new(str)
click to toggle source
# File lib/rubic/lexer.rb, line 21 def initialize(str) @s = StringScanner.new(str) @state = :start end
Public Instance Methods
next_token()
click to toggle source
# File lib/rubic/lexer.rb, line 26 def next_token case @state when :start @s.skip(/\s+/) return EOT if @s.eos? case when @s.check(/[+-]?[.0-9]|[+-]i/) @state = :num_char next_token when @s.check(/#/) @state = :num_prefix next_token when @s.scan(/[()']/) [@s[0], nil] when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o) if KEYWORD_TABLE.key? @s[0] [KEYWORD_TABLE.fetch(@s[0]), nil] else [:IDENT, @s[0].to_sym] end when @s.scan(/"([^"]*)"/) [:STRING, @s[1]] else raise Rubic::ParseError, "unknown character #{@s.getch}" end when :num_prefix case when @s.scan(/#[eibodx]/) { '#e' => [:NUM_PREFIX_E, true], '#i' => [:NUM_PREFIX_I, false], '#b' => [:NUM_PREFIX_B, nil], '#o' => [:NUM_PREFIX_O, nil], '#d' => [:NUM_PREFIX_D, nil], '#x' => [:NUM_PREFIX_X, nil], }.fetch(@s[0]) else @state = :num_char next_token end when :num_char case when @s.check(/[+-]?[.0-9a-f\/]*i/i) # complex @state = :num_char_complex next_token when @s.scan(/\+/) [:U_PLUS, '+'] when @s.scan(/-/) [:U_MINUS, '-'] when @s.scan(/[@.0-9a-f\/]/i) [@s[0].downcase, @s[0].downcase] else @state = :num_wrapup next_token end when :num_char_complex case when @s.scan(/[-+@.0-9a-fi\/]/i) [@s[0].downcase, @s[0].downcase] else @state = :num_wrapup next_token end when :num_wrapup case when @s.eos? || @s.check(/[\s()";]/) # separator characters @state = :start [:NUM_END, nil] else @state = :start next_token end else # NOT REACHED raise "unknown state: #{@state}" end end