class Rouge::RegexLexer::StateDSL
Attributes
Public Class Methods
Source
# File lib/rouge/regex_lexer.rb, line 76 def initialize(name, &defn) @name = name @defn = defn @rules = [] @loaded = false @closed = false end
Public Instance Methods
Source
# File lib/rouge/regex_lexer.rb, line 100 def appended(&defn) parent_defn = @defn StateDSL.new(@name) do instance_eval(&parent_defn) instance_eval(&defn) end end
Source
# File lib/rouge/regex_lexer.rb, line 92 def prepended(&defn) parent_defn = @defn StateDSL.new(@name) do instance_eval(&defn) instance_eval(&parent_defn) end end
Source
# File lib/rouge/regex_lexer.rb, line 84 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
Protected Instance Methods
Source
# File lib/rouge/regex_lexer.rb, line 190 def context_sensitive?(re) source = re.source return true if source =~ /[(][?]<?[!=]/ # anchors count as lookahead/behind return true if source =~ /[$^]/ false end
Source
# File lib/rouge/regex_lexer.rb, line 207 def mixin(state) rules << state.to_s end
Mix in the rules from another state into this state. The rules from the mixed-in state will be tried in order before moving on to the rest of the rules in this state.
Source
# File lib/rouge/regex_lexer.rb, line 128 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
Define a new rule for this state.
@overload rule(re, token, next_state=nil) @overload rule(re, &callback)
@param [Regexp] re
a regular expression for this rule to test.
@param [String] tok
the token type to yield if `re` matches.
@param [#to_s] next_state
(optional) a state to push onto the stack if `re` matches. If `next_state` is `:pop!`, the state stack will be popped instead.
@param [Proc] callback
a block that will be evaluated in the context of the lexer if `re` matches. This block has access to a number of lexer methods, including {RegexLexer#push}, {RegexLexer#pop!}, {RegexLexer#token}, and {RegexLexer#delegate}. The first argument can be used to access the match groups.
Private Instance Methods
Source
# File lib/rouge/regex_lexer.rb, line 212 def load! return if @loaded @loaded = true instance_eval(&@defn) end