class Rouge::RegexLexer::StateDSL
def appended(&defn)
def appended(&defn) parent_defn = @defn StateDSL.new(@name) do instance_eval(&parent_defn) instance_eval(&defn) end end
def close!
def close! @closed = true end
def context_sensitive?(re)
def context_sensitive?(re) source = re.source return true if source =~ /[(][?]<?[!=]/ # anchors count as lookahead/behind return true if source =~ /[$^]/ false end
def initialize(name, &defn)
def initialize(name, &defn) @name = name @defn = defn @rules = [] @loaded = false @closed = false end
def load!
def load! return if @loaded @loaded = true instance_eval(&@defn) end
def mixin(state)
from the mixed-in state will be tried in order before moving on
Mix in the rules from another state into this state. The rules
def mixin(state) rules << state.to_s end
def prepended(&defn)
def prepended(&defn) parent_defn = @defn StateDSL.new(@name) do instance_eval(&defn) instance_eval(&parent_defn) end end
def rule(re, tok=nil, next_state=nil, &callback)
-
callback
(Proc
) -- -
next_state
(#to_s
) -- -
tok
(String
) -- -
re
(Regexp
) --
Overloads:
-
rule(re, &callback)
-
rule(re, token, next_state=nil)
def rule(re, tok=nil, next_state=nil, &callback) raise ClosedState.new(self) if @closed if tok.nil? && callback.nil? raise "please pass `rule` a token to yield or a callback" end matches_empty = re =~ '' callback ||= case next_state when :pop! proc do |stream| puts " yielding: #{tok.qualname}, #{stream[0].inspect}" if @debug @output_stream.call(tok, stream[0]) puts " popping stack: 1" if @debug @stack.pop or raise 'empty stack!' end when :push proc do |stream| puts " yielding: #{tok.qualname}, #{stream[0].inspect}" if @debug @output_stream.call(tok, stream[0]) puts " pushing :#{@stack.last.name}" if @debug @stack.push(@stack.last) end when Symbol proc do |stream| puts " yielding: #{tok.qualname}, #{stream[0].inspect}" if @debug @output_stream.call(tok, stream[0]) state = @states[next_state] || self.class.get_state(next_state) puts " pushing :#{state.name}" if @debug @stack.push(state) end when nil # cannot use an empty-matching regexp with no predicate raise InvalidRegex.new(re) if matches_empty proc do |stream| puts " yielding: #{tok.qualname}, #{stream[0].inspect}" if @debug @output_stream.call(tok, stream[0]) end when Array proc do |stream| puts " yielding: #{tok.qualname}, #{stream[0].inspect}" if @debug @output_stream.call(tok, stream[0]) for i_next_state in next_state do next @stack.pop if i_next_state == :pop! next @stack.push(@stack.last) if i_next_state == :push state = @states[i_next_state] || self.class.get_state(i_next_state) puts " pushing :#{state.name}" if @debug @stack.push(state) end end else raise "invalid next state: #{next_state.inspect}" end rules << Rule.new(re, callback) close! if matches_empty && !context_sensitive?(re) end
def to_state(lexer_class)
def to_state(lexer_class) load! rules = @rules.map do |rule| rule.is_a?(String) ? lexer_class.get_state(rule) : rule end State.new(@name, rules) end