ruby/lib/rdoc/ruby_token.rb

460 строки
11 KiB
Ruby
Исходник Обычный вид История

#--
# irb/ruby-token.rb - ruby tokens
# $Release Version: 0.9.5$
# $Revision: 11708 $
# $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#++
# Definitions of all tokens involved in the lexical analysis.
#
# This class is not documented because it is so deep in the internals.
module RDoc::RubyToken
# :stopdoc:
EXPR_BEG = :EXPR_BEG
EXPR_MID = :EXPR_MID
EXPR_END = :EXPR_END
EXPR_ARG = :EXPR_ARG
EXPR_FNAME = :EXPR_FNAME
EXPR_DOT = :EXPR_DOT
EXPR_CLASS = :EXPR_CLASS
# for ruby 1.4X
if !defined?(Symbol)
Symbol = Integer
end
def set_token_position(line, char)
@prev_line_no = line
@prev_char_no = char
end
class Token
def initialize(seek, line_no, char_no, text = nil)
@seek = seek
@line_no = line_no
@char_no = char_no
@text = text
end
attr :seek
attr :line_no
attr :char_no
attr_accessor :text
def ==(other)
self.class == other.class and
other.line_no == @line_no and
other.char_no == @char_no and
other.text == @text
end
##
# Because we're used in contexts that expect to return a token, we set the
# text string and then return ourselves
def set_text(text)
@text = text
self
end
def inspect # :nodoc:
klass = self.class.name.split('::').last
"{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @text]
end
end
class TkNode < Token
def initialize(seek, line_no, char_no, node = nil)
super seek, line_no, char_no
@node = node
end
attr :node
def ==(other)
self.class == other.class and
other.line_no == @line_no and
other.char_no == @char_no and
other.node == @node
end
def set_text text
@node = text
self
end
alias text node
def inspect # :nodoc:
klass = self.class.name.split('::').last
"{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @node]
end
end
class TkId < Token
def initialize(seek, line_no, char_no, name)
super(seek, line_no, char_no)
@name = name
end
attr :name
def ==(other)
self.class == other.class and
other.line_no == @line_no and
other.char_no == @char_no and
other.name == @name
end
def set_text text
@name = text
self
end
alias text name
def inspect # :nodoc:
klass = self.class.name.split('::').last
"{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name]
end
end
class TkKW < TkId
end
class TkVal < Token
def initialize(seek, line_no, char_no, value = nil)
super(seek, line_no, char_no)
@value = value
end
attr_accessor :value
def ==(other)
self.class == other.class and
other.line_no == @line_no and
other.char_no == @char_no and
other.value == @value
end
def set_text text
@value = text
self
end
alias text value
def inspect # :nodoc:
klass = self.class.name.split('::').last
"{%s %s, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @value]
end
end
class TkOp < Token
def initialize(seek, line_no, char_no, name = nil)
super seek, line_no, char_no
@name = name
end
attr_accessor :name
def ==(other)
self.class == other.class and
other.line_no == @line_no and
other.char_no == @char_no and
other.name == @name
end
def set_text text
@name = text
self
end
alias text name
def inspect # :nodoc:
klass = self.class.name.split('::').last
"{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name]
end
end
class TkOPASGN < TkOp
def initialize(seek, line_no, char_no, op)
super(seek, line_no, char_no)
op = TkReading2Token[op][0] unless op.kind_of?(Symbol)
@op = op
@text = nil
end
attr :op
def ==(other)
self.class == other.class and
other.line_no == @line_no and
other.char_no == @char_no and
other.op == @op
end
def text
@text ||= "#{TkToken2Reading[op]}="
end
def inspect # :nodoc:
klass = self.class.name.split('::').last
"{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @op]
end
end
class TkUnknownChar < Token
def initialize(seek, line_no, char_no, name)
super(seek, line_no, char_no)
@name = name
end
attr :name
def ==(other)
self.class == other.class and
other.line_no == @line_no and
other.char_no == @char_no and
other.name == @name
end
def set_text text
@name = text
self
end
alias text name
def inspect # :nodoc:
klass = self.class.name.split('::').last
"{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name]
end
end
class TkError < Token
end
def Token(token, value = nil)
value ||= TkToken2Reading[token]
case token
when String
if (tk = TkReading2Token[token]).nil?
IRB.fail TkReading2TokenNoKey, token
end
tk = Token(tk[0], value)
if tk.kind_of?(TkOp) then
tk.name = token
end
when Symbol
if (tk = TkSymbol2Token[token]).nil?
IRB.fail TkSymbol2TokenNoKey, token
end
tk = Token(tk[0], value)
else
if token.instance_method(:initialize).arity == 3 then
tk = token.new(@prev_seek, @prev_line_no, @prev_char_no)
tk.set_text value
else
tk = token.new(@prev_seek, @prev_line_no, @prev_char_no, value)
end
end
tk
end
TokenDefinitions = [
[:TkCLASS, TkKW, "class", EXPR_CLASS],
[:TkMODULE, TkKW, "module", EXPR_BEG],
[:TkDEF, TkKW, "def", EXPR_FNAME],
[:TkUNDEF, TkKW, "undef", EXPR_FNAME],
[:TkBEGIN, TkKW, "begin", EXPR_BEG],
[:TkRESCUE, TkKW, "rescue", EXPR_MID],
[:TkENSURE, TkKW, "ensure", EXPR_BEG],
[:TkEND, TkKW, "end", EXPR_END],
[:TkIF, TkKW, "if", EXPR_BEG, :TkIF_MOD],
[:TkUNLESS, TkKW, "unless", EXPR_BEG, :TkUNLESS_MOD],
[:TkTHEN, TkKW, "then", EXPR_BEG],
[:TkELSIF, TkKW, "elsif", EXPR_BEG],
[:TkELSE, TkKW, "else", EXPR_BEG],
[:TkCASE, TkKW, "case", EXPR_BEG],
[:TkWHEN, TkKW, "when", EXPR_BEG],
[:TkWHILE, TkKW, "while", EXPR_BEG, :TkWHILE_MOD],
[:TkUNTIL, TkKW, "until", EXPR_BEG, :TkUNTIL_MOD],
[:TkFOR, TkKW, "for", EXPR_BEG],
[:TkBREAK, TkKW, "break", EXPR_MID],
[:TkNEXT, TkKW, "next", EXPR_END],
[:TkREDO, TkKW, "redo", EXPR_END],
[:TkRETRY, TkKW, "retry", EXPR_END],
[:TkIN, TkKW, "in", EXPR_BEG],
[:TkDO, TkKW, "do", EXPR_BEG],
[:TkRETURN, TkKW, "return", EXPR_MID],
[:TkYIELD, TkKW, "yield", EXPR_END],
[:TkSUPER, TkKW, "super", EXPR_END],
[:TkSELF, TkKW, "self", EXPR_END],
[:TkNIL, TkKW, "nil", EXPR_END],
[:TkTRUE, TkKW, "true", EXPR_END],
[:TkFALSE, TkKW, "false", EXPR_END],
[:TkAND, TkKW, "and", EXPR_BEG],
[:TkOR, TkKW, "or", EXPR_BEG],
[:TkNOT, TkKW, "not", EXPR_BEG],
[:TkIF_MOD, TkKW],
[:TkUNLESS_MOD, TkKW],
[:TkWHILE_MOD, TkKW],
[:TkUNTIL_MOD, TkKW],
[:TkALIAS, TkKW, "alias", EXPR_FNAME],
[:TkDEFINED, TkKW, "defined?", EXPR_END],
[:TklBEGIN, TkKW, "BEGIN", EXPR_END],
[:TklEND, TkKW, "END", EXPR_END],
[:Tk__LINE__, TkKW, "__LINE__", EXPR_END],
[:Tk__FILE__, TkKW, "__FILE__", EXPR_END],
[:TkIDENTIFIER, TkId],
[:TkFID, TkId],
[:TkGVAR, TkId],
[:TkCVAR, TkId],
[:TkIVAR, TkId],
[:TkCONSTANT, TkId],
[:TkINTEGER, TkVal],
[:TkFLOAT, TkVal],
[:TkSTRING, TkVal],
[:TkHEREDOC, TkVal],
[:TkXSTRING, TkVal],
[:TkREGEXP, TkVal],
[:TkSYMBOL, TkVal],
[:TkDSTRING, TkNode],
[:TkDXSTRING, TkNode],
[:TkDREGEXP, TkNode],
[:TkNTH_REF, TkNode],
[:TkBACK_REF, TkNode],
[:TkUPLUS, TkOp, "+@"],
[:TkUMINUS, TkOp, "-@"],
[:TkPOW, TkOp, "**"],
[:TkCMP, TkOp, "<=>"],
[:TkEQ, TkOp, "=="],
[:TkEQQ, TkOp, "==="],
[:TkNEQ, TkOp, "!="],
[:TkGEQ, TkOp, ">="],
[:TkLEQ, TkOp, "<="],
[:TkANDOP, TkOp, "&&"],
[:TkOROP, TkOp, "||"],
[:TkMATCH, TkOp, "=~"],
[:TkNMATCH, TkOp, "!~"],
[:TkDOT2, TkOp, ".."],
[:TkDOT3, TkOp, "..."],
[:TkAREF, TkOp, "[]"],
[:TkASET, TkOp, "[]="],
[:TkLSHFT, TkOp, "<<"],
[:TkRSHFT, TkOp, ">>"],
[:TkCOLON2, TkOp, '::'],
[:TkCOLON3, TkOp, '::'],
#[:OPASGN, TkOp], # +=, -= etc. #
[:TkASSOC, TkOp, "=>"],
[:TkQUESTION, TkOp, "?"], #?
[:TkCOLON, TkOp, ":"], #:
[:TkfLPAREN, Token, "("], # func( #
[:TkfLBRACK, Token, "["], # func[ #
[:TkfLBRACE, Token, "{"], # func{ #
[:TkSYMBEG, Token, ":"], # :SYMBOL
[:TkAMPER, TkOp, "&"],
[:TkGT, TkOp, ">"],
[:TkLT, TkOp, "<"],
[:TkPLUS, TkOp, "+"],
[:TkSTAR, TkOp, "*"],
[:TkMINUS, TkOp, "-"],
[:TkMULT, TkOp, "*"],
[:TkDIV, TkOp, "/"],
[:TkMOD, TkOp, "%"],
[:TkBITOR, TkOp, "|"],
[:TkBITXOR, TkOp, "^"],
[:TkBITAND, TkOp, "&"],
[:TkBITNOT, TkOp, "~"],
[:TkNOTOP, TkOp, "!"],
[:TkBACKQUOTE, TkOp, "`"],
[:TkASSIGN, Token, "="],
[:TkDOT, Token, "."],
[:TkLPAREN, Token, "("], #(exp)
[:TkLBRACK, Token, "["], #[arry]
[:TkLBRACE, Token, "{"], #{hash}
[:TkRPAREN, Token, ")"],
[:TkRBRACK, Token, "]"],
[:TkRBRACE, Token, "}"],
[:TkCOMMA, Token, ","],
[:TkSEMICOLON, Token, ";"],
[:TkCOMMENT, TkVal],
[:TkSPACE, Token, " "],
[:TkNL, Token, "\n"],
[:TkEND_OF_SCRIPT],
[:TkBACKSLASH, TkUnknownChar, "\\"],
[:TkAT, TkUnknownChar, "@"],
[:TkDOLLAR, TkUnknownChar, "$"],
]
# {reading => token_class}
# {reading => [token_class, *opt]}
TkReading2Token = {}
TkToken2Reading = {}
TkSymbol2Token = {}
def self.def_token(token_n, super_token = Token, reading = nil, *opts)
token_n = token_n.id2name if token_n.kind_of?(Symbol)
if const_defined?(token_n)
IRB.fail AlreadyDefinedToken, token_n
end
token_c = eval("class #{token_n} < #{super_token}; end; #{token_n}")
if reading
TkToken2Reading[token_c] = reading
return if TkReading2Token[reading]
if opts.empty?
TkReading2Token[reading] = [token_c]
else
TkReading2Token[reading] = [token_c].concat(opts)
end
end
TkSymbol2Token[token_n.intern] = token_c
end
for defs in TokenDefinitions
def_token(*defs)
end
def_token :TkRD_COMMENT, TkCOMMENT
NEWLINE_TOKEN = TkNL.new 0, 0, 0, "\n"
class TkSYMBOL
def to_sym
@sym ||= text[1..-1].intern
end
end
# :startdoc:
end