class Rouge::RegexLexer
def self.[](name)
def self.[](name) get_state(name) end
def self.get_state(name)
def self.get_state(name) return name if name.is_a? State state = states[name.to_s] raise "unknown state: #{name}" unless state state.load! end
def self.start(&b)
def self.start(&b) start_procs << b end
def self.start_procs
def self.start_procs @start_procs ||= [] end
def self.state(name, &b)
def self.state(name, &b) name = name.to_s states[name] = State.new(self, name, &b) end
def self.states
def self.states @states ||= {} end
def get_state(name)
def get_state(name) self.class.get_state(name) end
def reset!
def reset! @scan_state = nil self.class.start_procs.each do |pr| scan_state.instance_eval(&pr) end end
def run_rule(rule, scan_state, &b)
def run_rule(rule, scan_state, &b) case rule when String debug { " entering mixin #{rule}" } res = step(get_state(rule), scan_state, &b) debug { " exiting mixin #{rule}" } res when Rule debug { " trying #{rule.inspect}" } scan_state.scan(rule.re) do |match| debug { " got #{match[0].inspect}" } scan_state.run_callback(&rule.callback).each do |tok, res| debug { " yielding #{tok.to_s.inspect}, #{res.inspect}" } b.call(Token[tok], res) end end end end
def scan_state
def scan_state @scan_state ||= ScanState.new(self) end
def step(state, scan_state, &b)
def step(state, scan_state, &b) state.rules.each do |rule| return true if run_rule(rule, scan_state, &b) end false end
def stream_tokens(stream, &b)
def stream_tokens(stream, &b) scan_state.scanner = stream until scan_state.eos? debug { "lexer: #{self.class.tag}" } debug { "stack: #{scan_state.stack.map(&:name).inspect}" } debug { "stream: #{scan_state.scanner.peek(20).inspect}" } success = step(get_state(scan_state.state), scan_state, &b) if !success debug { " no match, yielding Error" } b.call(Token['Error'], scan_state.scanner.getch) end end end