#Copyright (c) 2011 Caleb Clausen class RubyLexer class Rule def initialize(lead,matcher,*actions) fail unless String===lead or Fixnum===lead @lead,@matcher,@actions=lead,matcher,actions end end class Mode #set of Rules def initialize(rules) rules.map!{|r| Rule.new(*r) } @rules=rules fail if rules.size>255 rules.each_with_index{|r,i| all_chars_of(r.lead).each{|char| @chartable[char]||='' @chartable[char]<:error, :default=>OpMode} ) OpMode=CommonMode|Mode.new( [";,", /./, OperatorToken] ["%/^", /.=?/, :could_be_assign, OperatorToken] ["&*+-", /(.)\1?=?/, :could_be_assign, OperatorToken], [?|, /\|\|?=?/, :could_be_assign, :could_be_end_goalpost, OperatorToken], [?<, /<<=?/, :could_be_assign, OperatorToken], [?>, />>=?/, :could_be_assign, OperatorToken], [?<, /<=?>?/, OperatorToken], #also gets <> [?>, />=?/, OperatorToken], [?=, /=(~|>|=?=?)/, :could_be_assign, OperatorToken] ["0-9",huh,:error] [letters,huh,:error] [?:, /::(?=#{ews}[#{uc_letter}][#{letter}]*(?![?`~@${\(]|!([^=]|$)#{ews_no_nl}#{definately_val}))/, OperatorToken] [?:, /::/, OperatorToken, MethodNameMode] #constant if capitalized and not followed by (implicit or explicit) param list and not ending in ? or ! , else method [?:, /:/, OperatorToken] [?., /\.\.\.?/, OperatorToken] [?., /\.(?!\.)/, OperatorToken, MethodNameMode] [?{, /./, :push_context, :push_soft_scope, :block_start, :maybe_goalposts, huhToken] [?}, /./, :pop_context, :pop_soft_scope?, :block_end?, huhToken, OpMode] ['])', /./, :pop_context, huhToken, OpMode] [/and|or|if|unless|while|until|rescue/, OperatorToken] [:do, :must_be_after_rparen, :push_soft_scope, :maybe_goalposts, KeywordToken] [:do, :if_allowed, KeywordToken] [:end, :pop_hard_scope?, :pop_context, OpMode] {:others=>:error, :default=>ValueMode} ) MethodNameMode=CommonMode|Mode.new( [letters, method, MethodNameToken], [?`,/./, huh, MethodNameToken], [huh, operator_method, MethodNameToken] [?[, /\[\]=?/, MethodNameToken] #[?(] #in ruby 1.9 {:default=>JustAfterMethodMode} ) JustAfterMethodMode=OpMode|Mode.new( [ws, /[#{ws}]+/, WhitespaceToken, AfterMethodMode], #[?\\] #hrm? [?(,huh,:push_context, ParamListStartToken, ValueMode] [?{,huh,:push_context, :push_soft_scope, :block_start, huhToken, ValueMode] [huh nil, /(?= [^#{ws}({] )/x, :no_token, OpMode] ) AfterMethodMode=Mode.new( #these indicate implicit parens unless followed by ws [?/, /./, StringStartToken, :iparen, :push_context, string_mode(?"){?/}], ['+-*&',huh, :iparen, ValueMode] #[?^] [?%,huh,] [?`,huh,] [?:,huh,] #tricky... operator in ternary context, else always symbol #these indicate implicit parens always [?[, //, :iparen, ValueMode] [lc_letters, //, :iparen, OpMode] ["$@A-Z", //, :iparen, OpMode] ["0-9", //, :iparen, OpMode] [%[~!], //, :iparen, ValueMode] [?<, /(?=<<-?['"#{lc_letters}])/i, :iparen, OpMode] [?{, //, :iparens2, OpMode] [?=, //, :iparens2, OpMode] [?;, //, :iparens2, OpMode] [?(] #tricky, need to look ahead for commas [")]}",/./,:iparens2, OpMode] [] {:default=>huh} ) AfterNewline=Mode.new StringInteriorMode=Mode.new end