# -*- mode: ruby; coding: us-ascii -*- firstline, predefined = __LINE__+1, %[\ max min hash freeze nil? inspect intern object_id const_added const_missing method_missing MethodMissing method_added singleton_method_added method_removed singleton_method_removed method_undefined singleton_method_undefined length size gets succ each proc lambda send __send__ __recursive_key__ initialize initialize_copy initialize_clone initialize_dup to_int to_ary to_str to_sym to_hash to_proc to_io to_a to_s to_i to_f to_r bt bt_locations call mesg exception locals not NOT and AND or OR div divmod fdiv quo name nil path _ UScore # MUST be successive _1 NUMPARAM_1 _2 NUMPARAM_2 _3 NUMPARAM_3 _4 NUMPARAM_4 _5 NUMPARAM_5 _6 NUMPARAM_6 _7 NUMPARAM_7 _8 NUMPARAM_8 _9 NUMPARAM_9 "/*NULL*/" NULL empty? eql? default respond_to? Respond_to respond_to_missing? Respond_to_missing core#set_method_alias core#set_variable_alias core#undef_method core#define_method core#define_singleton_method core#set_postexe core#hash_merge_ptr core#hash_merge_kwd core#raise core#sprintf - debug#created_info $_ LASTLINE $~ BACKREF $! ERROR_INFO ] # VM ID OP Parser Token token_ops = %[\ Dot2 .. DOT2 Dot3 ... DOT3 BDot2 .. BDOT2 BDot3 ... BDOT3 UPlus +@ UPLUS UMinus -@ UMINUS Pow ** POW Cmp <=> CMP PLUS + MINUS - MULT * DIV / MOD % LTLT << LSHFT GTGT >> RSHFT LT < LE <= LEQ GT > GE >= GEQ Eq == EQ Eqq === EQQ Neq != NEQ Not ! And & Or | Backquote ` EqTilde =~ MATCH NeqTilde !~ NMATCH AREF [] ASET []= COLON2 :: ANDOP && OROP || ANDDOT &. ] class KeywordError < RuntimeError def self.raise(mesg, line) super(self, mesg, ["#{__FILE__}:#{line}", *caller]) end end def id2varname(token, prefix = nil) if /#/ =~ token token = "_#{token.gsub(/\W+/, '_')}" else token = token.sub(/\?/, 'P') token = prefix + token if prefix token.sub!(/\A[a-z]/) {$&.upcase} token.sub!(/\A\$/, "_G_") token.sub!(/\A@@/, "_C_") token.sub!(/\A@/, "_I_") token.gsub!(/\W+/, "") end token end predefined_ids = {} preserved_ids = [] local_ids = [] instance_ids = [] global_ids = [] const_ids = [] class_ids = [] attrset_ids = [] token_op_ids = [] names = {} predefined.split(/^/).each_with_index do |line, num| next if /^#/ =~ line line.sub!(/\s+#.*/, '') name, token = line.split next unless name token = id2varname(token || name) if name == '-' preserved_ids << token next end if prev = names[name] KeywordError.raise("#{name} is already registered at line #{prev+firstline}", firstline+num) end if prev = predefined_ids[token] KeywordError.raise("#{token} is already used for #{prev} at line #{names[prev]+firstline}", firstline+num) end names[name] = num case name when /\A[A-Z]\w*\z/; const_ids when /\A(?!\d)\w+\z/; local_ids when /\A\$(?:\d+|(?!\d)\w+|\W)\z/; global_ids when /\A@@(?!\d)\w+\z/; class_ids when /\A@(?!\d)\w+\z/; instance_ids when /\A((?!\d)\w+)=\z/; attrset_ids else preserved_ids end << token predefined_ids[token] = name end index = 127 token_ops.split(/^/).each do |line| next if /^#/ =~ line line.sub!(/\s+#.*/, '') id, op, token = line.split next unless id and op token ||= (id unless /\A\W\z/ =~ op) token_op_ids << [id, op, token, (index += 1 if token)] end { "LOCAL" => local_ids, "INSTANCE" => instance_ids, "GLOBAL" => global_ids, "CONST" => const_ids, "CLASS" => class_ids, "ATTRSET" => attrset_ids, :preserved => preserved_ids, :predefined => predefined_ids, :token_op => token_op_ids, :last_token => index, }