1#!/usr/bin/ruby 2# encoding: utf-8 3 4require 'antlr3' 5 6module ANTLR3 7=begin rdoc ANTLR3::FilterMode 8 9If a lexer grammar specifies the <tt>filter = true</t> option, the generated 10Lexer code will include this module. It modifies the standard 11<tt>next_token</tt> to catch RecognitionErrors and skip ahead in the input until 12the token! method can match a token without raising a RecognitionError. 13 14See http://www.antlr.org/wiki/display/ANTLR3/Lexical+filters for more info on 15lexer filter mode. 16 17=end 18module FilterMode 19 def next_token 20 # if at end-of-file, return the EOF token 21 @input.peek == ANTLR3::EOF and return ANTLR3::EOF_TOKEN 22 23 @state.token = nil 24 @state.channel = ANTLR3::DEFAULT_CHANNEL 25 @state.token_start_position = @input.index 26 @state.token_start_column = @input.column 27 @state.token_start_line = @input.line 28 @state.text = nil 29 @state.backtracking = 1 30 31 m = @input.mark 32 token! 33 @input.release( m ) 34 emit 35 return @state.token 36 rescue ANTLR3::BacktrackingFailed 37 # token! backtracks with synpred at backtracking==2 38 # and we set the synpredgate to allow actions at level 1. 39 @input.rewind( m ) 40 @input.consume # advance one char and try again 41 retry 42 rescue ANTLR3::Error::RecognitionError => re 43 # shouldn't happen in backtracking mode, but... 44 report_error( re ) 45 recover( re ) 46 ensure 47 @state.backtracking = 0 48 end 49 50 def memoize( rule, start_index, success ) 51 super( rule, start_index, success ) if @state.backtracking > 1 52 end 53 54 def already_parsed_rule?( rule ) 55 @state.backtracking > 1 ? super( rule ) : false 56 end 57end 58end 59