eaiovnaovbqoebvqoeavibavo bigdecimal/newton.rb000064400000003435147635147470010512 0ustar00require "bigdecimal/ludcmp" require "bigdecimal/jacobian" # # newton.rb # # Solves the nonlinear algebraic equation system f = 0 by Newton's method. # This program is not dependent on BigDecimal. # # To call: # n = nlsolve(f,x) # where n is the number of iterations required, # x is the initial value vector # f is an Object which is used to compute the values of the equations to be solved. # It must provide the following methods: # # f.values(x):: returns the values of all functions at x # # f.zero:: returns 0.0 # f.one:: returns 1.0 # f.two:: returns 2.0 # f.ten:: returns 10.0 # # f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. # # On exit, x is the solution vector. # module Newton include LUSolve include Jacobian module_function def norm(fv,zero=0.0) s = zero n = fv.size for i in 0...n do s += fv[i]*fv[i] end s end def nlsolve(f,x) nRetry = 0 n = x.size f0 = f.values(x) zero = f.zero one = f.one two = f.two p5 = one/two d = norm(f0,zero) minfact = f.ten*f.ten*f.ten minfact = one/minfact e = f.eps while d >= e do nRetry += 1 # Not yet converged. => Compute Jacobian matrix dfdx = jacobian(f,f0,x) # Solve dfdx*dx = -f0 to estimate dx dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero) fact = two xs = x.dup begin fact *= p5 if fact < minfact then raise "Failed to reduce function values." end for i in 0...n do x[i] = xs[i] - dx[i]*fact end f0 = f.values(x) dn = norm(f0,zero) end while(dn>=d) d = dn end nRetry end end bigdecimal/jacobian.rb000064400000004073147635147470010745 0ustar00# # require 'bigdecimal/jacobian' # # Provides methods to compute the Jacobian matrix of a set of equations at a # point x. In the methods below: # # f is an Object which is used to compute the Jacobian matrix of the equations. # It must provide the following methods: # # f.values(x):: returns the values of all functions at x # # f.zero:: returns 0.0 # f.one:: returns 1.0 # f.two:: returns 2.0 # f.ten:: returns 10.0 # # f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. # # x is the point at which to compute the Jacobian. # # fx is f.values(x). # module Jacobian module_function # Determines the equality of two numbers by comparing to zero, or using the epsilon value def isEqual(a,b,zero=0.0,e=1.0e-8) aa = a.abs bb = b.abs if aa == zero && bb == zero then true else if ((a-b)/(aa+bb)).abs < e then true else false end end end # Computes the derivative of f[i] at x[i]. # fx is the value of f at x. def dfdxi(f,fx,x,i) nRetry = 0 n = x.size xSave = x[i] ok = 0 ratio = f.ten*f.ten*f.ten dx = x[i].abs/ratio dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps) dx = f.one/f.ten if isEqual(dx,f.zero,f.zero,f.eps) until ok>0 do s = f.zero deriv = [] nRetry += 1 if nRetry > 100 raise "Singular Jacobian matrix. No change at x[" + i.to_s + "]" end dx = dx*f.two x[i] += dx fxNew = f.values(x) for j in 0...n do if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then ok += 1 deriv <<= (fxNew[j]-fx[j])/dx else deriv <<= f.zero end end x[i] = xSave end deriv end # Computes the Jacobian of f at x. fx is the value of f at x. def jacobian(f,fx,x) n = x.size dfdx = Array::new(n*n) for i in 0...n do df = dfdxi(f,fx,x,i) for j in 0...n do dfdx[j*n+i] = df[j] end end dfdx end end bigdecimal/util.rb000064400000004376147635147470010162 0ustar00class Integer < Numeric # call-seq: # int.to_d -> bigdecimal # # Convert +int+ to a BigDecimal and return it. # # require 'bigdecimal' # require 'bigdecimal/util' # # 42.to_d # # => # # def to_d BigDecimal(self) end end class Float < Numeric # call-seq: # flt.to_d -> bigdecimal # # Convert +flt+ to a BigDecimal and return it. # # require 'bigdecimal' # require 'bigdecimal/util' # # 0.5.to_d # # => # # def to_d(precision=nil) BigDecimal(self, precision || Float::DIG+1) end end class String # call-seq: # string.to_d -> bigdecimal # # Convert +string+ to a BigDecimal and return it. # # require 'bigdecimal' # require 'bigdecimal/util' # # "0.5".to_d # # => # # def to_d BigDecimal(self) end end class BigDecimal < Numeric # call-seq: # a.to_digits -> string # # Converts a BigDecimal to a String of the form "nnnnnn.mmm". # This method is deprecated; use BigDecimal#to_s("F") instead. # # require 'bigdecimal' # require 'bigdecimal/util' # # d = BigDecimal.new("3.14") # d.to_digits # # => "3.14" def to_digits if self.nan? || self.infinite? || self.zero? self.to_s else i = self.to_i.to_s _,f,_,z = self.frac.split i + "." + ("0"*(-z)) + f end end # call-seq: # a.to_d -> bigdecimal # # Returns self. def to_d self end end class Rational < Numeric # call-seq: # r.to_d(precision) -> bigdecimal # # Converts a Rational to a BigDecimal. # # The required +precision+ parameter is used to determine the amount of # significant digits for the result. See BigDecimal#div for more information, # as it is used along with the #denominator and the +precision+ for # parameters. # # r = (22/7.0).to_r # # => (7077085128725065/2251799813685248) # r.to_d(3) # # => # def to_d(precision) if precision <= 0 raise ArgumentError, "negative precision" end num = self.numerator BigDecimal(num).div(self.denominator, precision) end end bigdecimal/ludcmp.rb000064400000004142147635147470010460 0ustar00require 'bigdecimal' # # Solves a*x = b for x, using LU decomposition. # module LUSolve module_function # Performs LU decomposition of the n by n matrix a. def ludecomp(a,n,zero=0,one=1) prec = BigDecimal.limit(nil) ps = [] scales = [] for i in 0...n do # pick up largest(abs. val.) element in each row. ps <<= i nrmrow = zero ixn = i*n for j in 0...n do biggst = a[ixn+j].abs nrmrow = biggst if biggst>nrmrow end if nrmrow>zero then scales <<= one.div(nrmrow,prec) else raise "Singular matrix" end end n1 = n - 1 for k in 0...n1 do # Gaussian elimination with partial pivoting. biggst = zero; for i in k...n do size = a[ps[i]*n+k].abs*scales[ps[i]] if size>biggst then biggst = size pividx = i end end raise "Singular matrix" if biggst<=zero if pividx!=k then j = ps[k] ps[k] = ps[pividx] ps[pividx] = j end pivot = a[ps[k]*n+k] for i in (k+1)...n do psin = ps[i]*n a[psin+k] = mult = a[psin+k].div(pivot,prec) if mult!=zero then pskn = ps[k]*n for j in (k+1)...n do a[psin+j] -= mult.mult(a[pskn+j],prec) end end end end raise "Singular matrix" if a[ps[n1]*n+n1] == zero ps end # Solves a*x = b for x, using LU decomposition. # # a is a matrix, b is a constant vector, x is the solution vector. # # ps is the pivot, a vector which indicates the permutation of rows performed # during LU decomposition. def lusolve(a,b,ps,zero=0.0) prec = BigDecimal.limit(nil) n = ps.size x = [] for i in 0...n do dot = zero psin = ps[i]*n for j in 0...i do dot = a[psin+j].mult(x[j],prec) + dot end x <<= b[ps[i]] - dot end (n-1).downto(0) do |i| dot = zero psin = ps[i]*n for j in (i+1)...n do dot = a[psin+j].mult(x[j],prec) + dot end x[i] = (x[i]-dot).div(a[psin+i],prec) end x end end bigdecimal/math.rb000064400000011742147635147470010131 0ustar00require 'bigdecimal' # #-- # Contents: # sqrt(x, prec) # sin (x, prec) # cos (x, prec) # atan(x, prec) Note: |x|<1, x=0.9999 may not converge. # PI (prec) # E (prec) == exp(1.0,prec) # # where: # x ... BigDecimal number to be computed. # |x| must be small enough to get convergence. # prec ... Number of digits to be obtained. #++ # # Provides mathematical functions. # # Example: # # require "bigdecimal" # require "bigdecimal/math" # # include BigMath # # a = BigDecimal((PI(100)/2).to_s) # puts sin(a,100) # -> 0.10000000000000000000......E1 # module BigMath module_function # Computes the square root of x to the specified number of digits of # precision. # # BigDecimal.new('2').sqrt(16).to_s # -> "0.14142135623730950488016887242096975E1" # def sqrt(x,prec) x.sqrt(prec) end # Computes the sine of x to the specified number of digits of precision. # # If x is infinite or NaN, returns NaN. def sin(x, prec) raise ArgumentError, "Zero or negative precision for sin" if prec <= 0 return BigDecimal("NaN") if x.infinite? || x.nan? n = prec + BigDecimal.double_fig one = BigDecimal("1") two = BigDecimal("2") x = -x if neg = x < 0 if x > (twopi = two * BigMath.PI(prec)) if x > 30 x %= twopi else x -= twopi while x > twopi end end x1 = x x2 = x.mult(x,n) sign = 1 y = x d = y i = one z = one while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) m = BigDecimal.double_fig if m < BigDecimal.double_fig sign = -sign x1 = x2.mult(x1,n) i += two z *= (i-one) * i d = sign * x1.div(z,m) y += d end neg ? -y : y end # Computes the cosine of x to the specified number of digits of precision. # # If x is infinite or NaN, returns NaN. def cos(x, prec) raise ArgumentError, "Zero or negative precision for cos" if prec <= 0 return BigDecimal("NaN") if x.infinite? || x.nan? n = prec + BigDecimal.double_fig one = BigDecimal("1") two = BigDecimal("2") x = -x if x < 0 if x > (twopi = two * BigMath.PI(prec)) if x > 30 x %= twopi else x -= twopi while x > twopi end end x1 = one x2 = x.mult(x,n) sign = 1 y = one d = y i = BigDecimal("0") z = one while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) m = BigDecimal.double_fig if m < BigDecimal.double_fig sign = -sign x1 = x2.mult(x1,n) i += two z *= (i-one) * i d = sign * x1.div(z,m) y += d end y end # Computes the arctangent of x to the specified number of digits of precision. # # If x is NaN, returns NaN. def atan(x, prec) raise ArgumentError, "Zero or negative precision for atan" if prec <= 0 return BigDecimal("NaN") if x.nan? pi = PI(prec) x = -x if neg = x < 0 return pi.div(neg ? -2 : 2, prec) if x.infinite? return pi / (neg ? -4 : 4) if x.round(prec) == 1 x = BigDecimal("1").div(x, prec) if inv = x > 1 x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5 n = prec + BigDecimal.double_fig y = x d = y t = x r = BigDecimal("3") x2 = x.mult(x,n) while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) m = BigDecimal.double_fig if m < BigDecimal.double_fig t = -t.mult(x2,n) d = t.div(r,m) y += d r += 2 end y *= 2 if dbl y = pi / 2 - y if inv y = -y if neg y end # Computes the value of pi to the specified number of digits of precision. def PI(prec) raise ArgumentError, "Zero or negative argument for PI" if prec <= 0 n = prec + BigDecimal.double_fig zero = BigDecimal("0") one = BigDecimal("1") two = BigDecimal("2") m25 = BigDecimal("-0.04") m57121 = BigDecimal("-57121") pi = zero d = one k = one w = one t = BigDecimal("-80") while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) m = BigDecimal.double_fig if m < BigDecimal.double_fig t = t*m25 d = t.div(k,m) k = k+two pi = pi + d end d = one k = one w = one t = BigDecimal("956") while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) m = BigDecimal.double_fig if m < BigDecimal.double_fig t = t.div(m57121,n) d = t.div(k,m) pi = pi + d k = k+two end pi end # Computes e (the base of natural logarithms) to the specified number of # digits of precision. def E(prec) raise ArgumentError, "Zero or negative precision for E" if prec <= 0 n = prec + BigDecimal.double_fig one = BigDecimal("1") y = one d = y z = one i = 0 while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) m = BigDecimal.double_fig if m < BigDecimal.double_fig i += 1 z *= i d = one.div(z,m) y += d end y end end psych.rb000064400000026720147635151770006246 0ustar00require 'psych.so' require 'psych/nodes' require 'psych/streaming' require 'psych/visitors' require 'psych/handler' require 'psych/tree_builder' require 'psych/parser' require 'psych/omap' require 'psych/set' require 'psych/coder' require 'psych/core_ext' require 'psych/deprecated' require 'psych/stream' require 'psych/json/tree_builder' require 'psych/json/stream' require 'psych/handlers/document_stream' ### # = Overview # # Psych is a YAML parser and emitter. # Psych leverages libyaml [Home page: http://pyyaml.org/wiki/LibYAML] # or [Git repo: https://github.com/zerotao/libyaml] for its YAML parsing # and emitting capabilities. In addition to wrapping libyaml, Psych also # knows how to serialize and de-serialize most Ruby objects to and from # the YAML format. # # = I NEED TO PARSE OR EMIT YAML RIGHT NOW! # # # Parse some YAML # Psych.load("--- foo") # => "foo" # # # Emit some YAML # Psych.dump("foo") # => "--- foo\n...\n" # { :a => 'b'}.to_yaml # => "---\n:a: b\n" # # Got more time on your hands? Keep on reading! # # == YAML Parsing # # Psych provides a range of interfaces for parsing a YAML document ranging from # low level to high level, depending on your parsing needs. At the lowest # level, is an event based parser. Mid level is access to the raw YAML AST, # and at the highest level is the ability to unmarshal YAML to ruby objects. # # === Low level parsing # # The lowest level parser should be used when the YAML input is already known, # and the developer does not want to pay the price of building an AST or # automatic detection and conversion to ruby objects. See Psych::Parser for # more information on using the event based parser. # # === Mid level parsing # # Psych provides access to an AST produced from parsing a YAML document. This # tree is built using the Psych::Parser and Psych::TreeBuilder. The AST can # be examined and manipulated freely. Please see Psych::parse_stream, # Psych::Nodes, and Psych::Nodes::Node for more information on dealing with # YAML syntax trees. # # === High level parsing # # The high level YAML parser provided by Psych simply takes YAML as input and # returns a Ruby data structure. For information on using the high level parser # see Psych.load # # == YAML Emitting # # Psych provides a range of interfaces ranging from low to high level for # producing YAML documents. Very similar to the YAML parsing interfaces, Psych # provides at the lowest level, an event based system, mid-level is building # a YAML AST, and the highest level is converting a Ruby object straight to # a YAML document. # # === Low level emitting # # The lowest level emitter is an event based system. Events are sent to a # Psych::Emitter object. That object knows how to convert the events to a YAML # document. This interface should be used when document format is known in # advance or speed is a concern. See Psych::Emitter for more information. # # === Mid level emitting # # At the mid level is building an AST. This AST is exactly the same as the AST # used when parsing a YAML document. Users can build an AST by hand and the # AST knows how to emit itself as a YAML document. See Psych::Nodes, # Psych::Nodes::Node, and Psych::TreeBuilder for more information on building # a YAML AST. # # === High level emitting # # The high level emitter has the easiest interface. Psych simply takes a Ruby # data structure and converts it to a YAML document. See Psych.dump for more # information on dumping a Ruby data structure. module Psych # The version is Psych you're using VERSION = '2.0.0' # The version of libyaml Psych is using LIBYAML_VERSION = Psych.libyaml_version.join '.' ### # Load +yaml+ in to a Ruby data structure. If multiple documents are # provided, the object contained in the first document will be returned. # +filename+ will be used in the exception message if any exception is raised # while parsing. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # # Example: # # Psych.load("--- a") # => 'a' # Psych.load("---\n - a\n - b") # => ['a', 'b'] # # begin # Psych.load("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end def self.load yaml, filename = nil result = parse(yaml, filename) result ? result.to_ruby : result end ### # Safely load the yaml string in +yaml+. By default, only the following # classes are allowed to be deserialized: # # * TrueClass # * FalseClass # * NilClass # * Numeric # * String # * Array # * Hash # # Recursive data structures are not allowed by default. Arbitrary classes # can be allowed by adding those classes to the +whitelist+. They are # additive. For example, to allow Date deserialization: # # Psych.safe_load(yaml, [Date]) # # Now the Date class can be loaded in addition to the classes listed above. # # Aliases can be explicitly allowed by changing the +aliases+ parameter. # For example: # # x = [] # x << x # yaml = Psych.dump x # Psych.safe_load yaml # => raises an exception # Psych.safe_load yaml, [], [], true # => loads the aliases # # A Psych::DisallowedClass exception will be raised if the yaml contains a # class that isn't in the whitelist. # # A Psych::BadAlias exception will be raised if the yaml contains aliases # but the +aliases+ parameter is set to false. def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil result = parse(yaml, filename) return unless result class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s), whitelist_symbols.map(&:to_s)) scanner = ScalarScanner.new class_loader if aliases visitor = Visitors::ToRuby.new scanner, class_loader else visitor = Visitors::NoAliasRuby.new scanner, class_loader end visitor.accept result end ### # Parse a YAML string in +yaml+. Returns the first object of a YAML AST. # +filename+ is used in the exception message if a Psych::SyntaxError is # raised. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # # Example: # # Psych.parse("---\n - a\n - b") # => # # # begin # Psych.parse("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end # # See Psych::Nodes for more information about YAML AST. def self.parse yaml, filename = nil parse_stream(yaml, filename) do |node| return node end false end ### # Parse a file at +filename+. Returns the YAML AST. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. def self.parse_file filename File.open filename, 'r:bom|utf-8' do |f| parse f, filename end end ### # Returns a default parser def self.parser Psych::Parser.new(TreeBuilder.new) end ### # Parse a YAML string in +yaml+. Returns the full AST for the YAML document. # This method can handle multiple YAML documents contained in +yaml+. # +filename+ is used in the exception message if a Psych::SyntaxError is # raised. # # If a block is given, a Psych::Nodes::Document node will be yielded to the # block as it's being parsed. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # # Example: # # Psych.parse_stream("---\n - a\n - b") # => # # # Psych.parse_stream("--- a\n--- b") do |node| # node # => # # end # # begin # Psych.parse_stream("--- `", "file.txt") # rescue Psych::SyntaxError => ex # ex.file # => 'file.txt' # ex.message # => "(file.txt): found character that cannot start any token" # end # # See Psych::Nodes for more information about YAML AST. def self.parse_stream yaml, filename = nil, &block if block_given? parser = Psych::Parser.new(Handlers::DocumentStream.new(&block)) parser.parse yaml, filename else parser = self.parser parser.parse yaml, filename parser.handler.root end end ### # call-seq: # Psych.dump(o) -> string of yaml # Psych.dump(o, options) -> string of yaml # Psych.dump(o, io) -> io object passed in # Psych.dump(o, io, options) -> io object passed in # # Dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in # to control the output format. If an IO object is passed in, the YAML will # be dumped to that IO object. # # Example: # # # Dump an array, get back a YAML string # Psych.dump(['a', 'b']) # => "---\n- a\n- b\n" # # # Dump an array to an IO object # Psych.dump(['a', 'b'], StringIO.new) # => # # # # Dump an array with indentation set # Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n" # # # Dump an array to an IO with indentation set # Psych.dump(['a', ['b']], StringIO.new, :indentation => 3) def self.dump o, io = nil, options = {} if Hash === io options = io io = nil end visitor = Psych::Visitors::YAMLTree.create options visitor << o visitor.tree.yaml io, options end ### # Dump a list of objects as separate documents to a document stream. # # Example: # # Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n" def self.dump_stream *objects visitor = Psych::Visitors::YAMLTree.create({}) objects.each do |o| visitor << o end visitor.tree.yaml end ### # Dump Ruby object +o+ to a JSON string. def self.to_json o visitor = Psych::Visitors::JSONTree.create visitor << o visitor.tree.yaml end ### # Load multiple documents given in +yaml+. Returns the parsed documents # as a list. If a block is given, each document will be converted to ruby # and passed to the block during parsing # # Example: # # Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar'] # # list = [] # Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby| # list << ruby # end # list # => ['foo', 'bar'] # def self.load_stream yaml, filename = nil if block_given? parse_stream(yaml, filename) do |node| yield node.to_ruby end else parse_stream(yaml, filename).children.map { |child| child.to_ruby } end end ### # Load the document contained in +filename+. Returns the yaml contained in # +filename+ as a ruby object def self.load_file filename File.open(filename, 'r:bom|utf-8') { |f| self.load f, filename } end # :stopdoc: @domain_types = {} def self.add_domain_type domain, type_tag, &block key = ['tag', domain, type_tag].join ':' @domain_types[key] = [key, block] @domain_types["tag:#{type_tag}"] = [key, block] end def self.add_builtin_type type_tag, &block domain = 'yaml.org,2002' key = ['tag', domain, type_tag].join ':' @domain_types[key] = [key, block] end def self.remove_type type_tag @domain_types.delete type_tag end @load_tags = {} @dump_tags = {} def self.add_tag tag, klass @load_tags[tag] = klass.name @dump_tags[klass] = tag end class << self attr_accessor :load_tags attr_accessor :dump_tags attr_accessor :domain_types end # :startdoc: end psych/core_ext.rb000064400000001357147635151770010055 0ustar00class Object def self.yaml_tag url Psych.add_tag(url, self) end # FIXME: rename this to "to_yaml" when syck is removed ### # call-seq: to_yaml(options = {}) # # Convert an object to YAML. See Psych.dump for more information on the # available +options+. def psych_to_yaml options = {} Psych.dump self, options end remove_method :to_yaml rescue nil alias :to_yaml :psych_to_yaml end class Module def psych_yaml_as url return if caller[0].end_with?('rubytypes.rb') if $VERBOSE warn "#{caller[0]}: yaml_as is deprecated, please use yaml_tag" end Psych.add_tag(url, self) end remove_method :yaml_as rescue nil alias :yaml_as :psych_yaml_as end if defined?(::IRB) require 'psych/y' end psych/omap.rb000064400000000055147635151770007173 0ustar00module Psych class Omap < ::Hash end end psych/stream.rb000064400000001575147635151770007542 0ustar00module Psych ### # Psych::Stream is a streaming YAML emitter. It will not buffer your YAML, # but send it straight to an IO. # # Here is an example use: # # stream = Psych::Stream.new($stdout) # stream.start # stream.push({:foo => 'bar'}) # stream.finish # # YAML will be immediately emitted to $stdout with no buffering. # # Psych::Stream#start will take a block and ensure that Psych::Stream#finish # is called, so you can do this form: # # stream = Psych::Stream.new($stdout) # stream.start do |em| # em.push(:foo => 'bar') # end # class Stream < Psych::Visitors::YAMLTree class Emitter < Psych::Emitter # :nodoc: def end_document implicit_end = !streaming? super end def streaming? true end end include Psych::Streaming extend Psych::Streaming::ClassMethods end end psych/y.rb000064400000000240147635151770006503 0ustar00module Kernel ### # An alias for Psych.dump_stream meant to be used with IRB. def y *objects puts Psych.dump_stream(*objects) end private :y end psych/visitors.rb000064400000000316147635151770010121 0ustar00require 'psych/visitors/visitor' require 'psych/visitors/to_ruby' require 'psych/visitors/emitter' require 'psych/visitors/yaml_tree' require 'psych/visitors/json_tree' require 'psych/visitors/depth_first' psych/parser.rb000064400000003221147635151770007531 0ustar00module Psych ### # YAML event parser class. This class parses a YAML document and calls # events on the handler that is passed to the constructor. The events can # be used for things such as constructing a YAML AST or deserializing YAML # documents. It can even be fed back to Psych::Emitter to emit the same # document that was parsed. # # See Psych::Handler for documentation on the events that Psych::Parser emits. # # Here is an example that prints out ever scalar found in a YAML document: # # # Handler for detecting scalar values # class ScalarHandler < Psych::Handler # def scalar value, anchor, tag, plain, quoted, style # puts value # end # end # # parser = Psych::Parser.new(ScalarHandler.new) # parser.parse(yaml_document) # # Here is an example that feeds the parser back in to Psych::Emitter. The # YAML document is read from STDIN and written back out to STDERR: # # parser = Psych::Parser.new(Psych::Emitter.new($stderr)) # parser.parse($stdin) # # Psych uses Psych::Parser in combination with Psych::TreeBuilder to # construct an AST of the parsed YAML document. class Parser class Mark < Struct.new(:index, :line, :column) end # The handler on which events will be called attr_accessor :handler # Set the encoding for this parser to +encoding+ attr_writer :external_encoding ### # Creates a new Psych::Parser instance with +handler+. YAML events will # be called on +handler+. See Psych::Parser for more details. def initialize handler = Handler.new @handler = handler @external_encoding = ANY end end end psych/handler.rb000064400000016024147635151770007657 0ustar00module Psych ### # Psych::Handler is an abstract base class that defines the events used # when dealing with Psych::Parser. Clients who want to use Psych::Parser # should implement a class that inherits from Psych::Handler and define # events that they can handle. # # Psych::Handler defines all events that Psych::Parser can possibly send to # event handlers. # # See Psych::Parser for more details class Handler ### # Configuration options for dumping YAML. class DumperOptions attr_accessor :line_width, :indentation, :canonical def initialize @line_width = 0 @indentation = 2 @canonical = false end end # Default dumping options OPTIONS = DumperOptions.new # Events that a Handler should respond to. EVENTS = [ :alias, :empty, :end_document, :end_mapping, :end_sequence, :end_stream, :scalar, :start_document, :start_mapping, :start_sequence, :start_stream ] ### # Called with +encoding+ when the YAML stream starts. This method is # called once per stream. A stream may contain multiple documents. # # See the constants in Psych::Parser for the possible values of +encoding+. def start_stream encoding end ### # Called when the document starts with the declared +version+, # +tag_directives+, if the document is +implicit+. # # +version+ will be an array of integers indicating the YAML version being # dealt with, +tag_directives+ is a list of tuples indicating the prefix # and suffix of each tag, and +implicit+ is a boolean indicating whether # the document is started implicitly. # # === Example # # Given the following YAML: # # %YAML 1.1 # %TAG ! tag:tenderlovemaking.com,2009: # --- !squee # # The parameters for start_document must be this: # # version # => [1, 1] # tag_directives # => [["!", "tag:tenderlovemaking.com,2009:"]] # implicit # => false def start_document version, tag_directives, implicit end ### # Called with the document ends. +implicit+ is a boolean value indicating # whether or not the document has an implicit ending. # # === Example # # Given the following YAML: # # --- # hello world # # +implicit+ will be true. Given this YAML: # # --- # hello world # ... # # +implicit+ will be false. def end_document implicit end ### # Called when an alias is found to +anchor+. +anchor+ will be the name # of the anchor found. # # === Example # # Here we have an example of an array that references itself in YAML: # # --- &ponies # - first element # - *ponies # # &ponies is the achor, *ponies is the alias. In this case, alias is # called with "ponies". def alias anchor end ### # Called when a scalar +value+ is found. The scalar may have an # +anchor+, a +tag+, be implicitly +plain+ or implicitly +quoted+ # # +value+ is the string value of the scalar # +anchor+ is an associated anchor or nil # +tag+ is an associated tag or nil # +plain+ is a boolean value # +quoted+ is a boolean value # +style+ is an integer idicating the string style # # See the constants in Psych::Nodes::Scalar for the possible values of # +style+ # # === Example # # Here is a YAML document that exercises most of the possible ways this # method can be called: # # --- # - !str "foo" # - &anchor fun # - many # lines # - | # many # newlines # # The above YAML document contains a list with four strings. Here are # the parameters sent to this method in the same order: # # # value anchor tag plain quoted style # ["foo", nil, "!str", false, false, 3 ] # ["fun", "anchor", nil, true, false, 1 ] # ["many lines", nil, nil, true, false, 1 ] # ["many\nnewlines\n", nil, nil, false, true, 4 ] # def scalar value, anchor, tag, plain, quoted, style end ### # Called when a sequence is started. # # +anchor+ is the anchor associated with the sequence or nil. # +tag+ is the tag associated with the sequence or nil. # +implicit+ a boolean indicating whether or not the sequence was implicitly # started. # +style+ is an integer indicating the list style. # # See the constants in Psych::Nodes::Sequence for the possible values of # +style+. # # === Example # # Here is a YAML document that exercises most of the possible ways this # method can be called: # # --- # - !!seq [ # a # ] # - &pewpew # - b # # The above YAML document consists of three lists, an outer list that # contains two inner lists. Here is a matrix of the parameters sent # to represent these lists: # # # anchor tag implicit style # [nil, nil, true, 1 ] # [nil, "tag:yaml.org,2002:seq", false, 2 ] # ["pewpew", nil, true, 1 ] def start_sequence anchor, tag, implicit, style end ### # Called when a sequence ends. def end_sequence end ### # Called when a map starts. # # +anchor+ is the anchor associated with the map or +nil+. # +tag+ is the tag associated with the map or +nil+. # +implicit+ is a boolean indicating whether or not the map was implicitly # started. # +style+ is an integer indicating the mapping style. # # See the constants in Psych::Nodes::Mapping for the possible values of # +style+. # # === Example # # Here is a YAML document that exercises most of the possible ways this # method can be called: # # --- # k: !!map { hello: world } # v: &pewpew # hello: world # # The above YAML document consists of three maps, an outer map that contains # two inner maps. Below is a matrix of the parameters sent in order to # represent these three maps: # # # anchor tag implicit style # [nil, nil, true, 1 ] # [nil, "tag:yaml.org,2002:map", false, 2 ] # ["pewpew", nil, true, 1 ] def start_mapping anchor, tag, implicit, style end ### # Called when a map ends def end_mapping end ### # Called when an empty event happens. (Which, as far as I can tell, is # never). def empty end ### # Called when the YAML stream ends def end_stream end ### # Is this handler a streaming handler? def streaming? false end end end psych/nodes.rb000064400000004515147635151770007354 0ustar00require 'psych/nodes/node' require 'psych/nodes/stream' require 'psych/nodes/document' require 'psych/nodes/sequence' require 'psych/nodes/scalar' require 'psych/nodes/mapping' require 'psych/nodes/alias' module Psych ### # = Overview # # When using Psych.load to deserialize a YAML document, the document is # translated to an intermediary AST. That intermediary AST is then # translated in to a Ruby object graph. # # In the opposite direction, when using Psych.dump, the Ruby object graph is # translated to an intermediary AST which is then converted to a YAML # document. # # Psych::Nodes contains all of the classes that make up the nodes of a YAML # AST. You can manually build an AST and use one of the visitors (see # Psych::Visitors) to convert that AST to either a YAML document or to a # Ruby object graph. # # Here is an example of building an AST that represents a list with one # scalar: # # # Create our nodes # stream = Psych::Nodes::Stream.new # doc = Psych::Nodes::Document.new # seq = Psych::Nodes::Sequence.new # scalar = Psych::Nodes::Scalar.new('foo') # # # Build up our tree # stream.children << doc # doc.children << seq # seq.children << scalar # # The stream is the root of the tree. We can then convert the tree to YAML: # # stream.to_yaml => "---\n- foo\n" # # Or convert it to Ruby: # # stream.to_ruby => [["foo"]] # # == YAML AST Requirements # # A valid YAML AST *must* have one Psych::Nodes::Stream at the root. A # Psych::Nodes::Stream node must have 1 or more Psych::Nodes::Document nodes # as children. # # Psych::Nodes::Document nodes must have one and *only* one child. That child # may be one of: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # # Psych::Nodes::Sequence and Psych::Nodes::Mapping nodes may have many # children, but Psych::Nodes::Mapping nodes should have an even number of # children. # # All of these are valid children for Psych::Nodes::Sequence and # Psych::Nodes::Mapping nodes: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # * Psych::Nodes::Alias # # Psych::Nodes::Scalar and Psych::Nodes::Alias are both terminal nodes and # should not have any children. module Nodes end end psych/nodes/stream.rb000064400000001705147635151770010645 0ustar00module Psych module Nodes ### # Represents a YAML stream. This is the root node for any YAML parse # tree. This node must have one or more child nodes. The only valid # child node for a Psych::Nodes::Stream node is Psych::Nodes::Document. class Stream < Psych::Nodes::Node # Encodings supported by Psych (and libyaml) # Any encoding ANY = Psych::Parser::ANY # UTF-8 encoding UTF8 = Psych::Parser::UTF8 # UTF-16LE encoding UTF16LE = Psych::Parser::UTF16LE # UTF-16BE encoding UTF16BE = Psych::Parser::UTF16BE # The encoding used for this stream attr_accessor :encoding ### # Create a new Psych::Nodes::Stream node with an +encoding+ that # defaults to Psych::Nodes::Stream::UTF8. # # See also Psych::Handler#start_stream def initialize encoding = UTF8 super() @encoding = encoding end end end end psych/nodes/document.rb000064400000003403147635151770011165 0ustar00module Psych module Nodes ### # This represents a YAML Document. This node must be a child of # Psych::Nodes::Stream. A Psych::Nodes::Document must have one child, # and that child may be one of the following: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar class Document < Psych::Nodes::Node # The version of the YAML document attr_accessor :version # A list of tag directives for this document attr_accessor :tag_directives # Was this document implicitly created? attr_accessor :implicit # Is the end of the document implicit? attr_accessor :implicit_end ### # Create a new Psych::Nodes::Document object. # # +version+ is a list indicating the YAML version. # +tags_directives+ is a list of tag directive declarations # +implicit+ is a flag indicating whether the document will be implicitly # started. # # == Example: # This creates a YAML document object that represents a YAML 1.1 document # with one tag directive, and has an implicit start: # # Psych::Nodes::Document.new( # [1,1], # [["!", "tag:tenderlovemaking.com,2009:"]], # true # ) # # == See Also # See also Psych::Handler#start_document def initialize version = [], tag_directives = [], implicit = false super() @version = version @tag_directives = tag_directives @implicit = implicit @implicit_end = true end ### # Returns the root node. A Document may only have one root node: # http://yaml.org/spec/1.1/#id898031 def root children.first end end end end psych/nodes/mapping.rb000064400000002754147635151770011012 0ustar00module Psych module Nodes ### # This class represents a {YAML Mapping}[http://yaml.org/spec/1.1/#mapping]. # # A Psych::Nodes::Mapping node may have 0 or more children, but must have # an even number of children. Here are the valid children a # Psych::Nodes::Mapping node may have: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # * Psych::Nodes::Alias class Mapping < Psych::Nodes::Node # Any Map Style ANY = 0 # Block Map Style BLOCK = 1 # Flow Map Style FLOW = 2 # The optional anchor for this mapping attr_accessor :anchor # The optional tag for this mapping attr_accessor :tag # Is this an implicit mapping? attr_accessor :implicit # The style of this mapping attr_accessor :style ### # Create a new Psych::Nodes::Mapping object. # # +anchor+ is the anchor associated with the map or +nil+. # +tag+ is the tag associated with the map or +nil+. # +implicit+ is a boolean indicating whether or not the map was implicitly # started. # +style+ is an integer indicating the mapping style. # # == See Also # See also Psych::Handler#start_mapping def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK super() @anchor = anchor @tag = tag @implicit = implicit @style = style end end end end psych/nodes/sequence.rb000064400000003742147635151770011165 0ustar00module Psych module Nodes ### # This class represents a # {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax]. # # A YAML sequence is basically a list, and looks like this: # # %YAML 1.1 # --- # - I am # - a Sequence # # A YAML sequence may have an anchor like this: # # %YAML 1.1 # --- # &A [ # "This sequence", # "has an anchor" # ] # # A YAML sequence may also have a tag like this: # # %YAML 1.1 # --- # !!seq [ # "This sequence", # "has a tag" # ] # # This class represents a sequence in a YAML document. A # Psych::Nodes::Sequence node may have 0 or more children. Valid children # for this node are: # # * Psych::Nodes::Sequence # * Psych::Nodes::Mapping # * Psych::Nodes::Scalar # * Psych::Nodes::Alias class Sequence < Psych::Nodes::Node # Any Styles, emitter chooses ANY = 0 # Block style sequence BLOCK = 1 # Flow style sequence FLOW = 2 # The anchor for this sequence (if any) attr_accessor :anchor # The tag name for this sequence (if any) attr_accessor :tag # Is this sequence started implicitly? attr_accessor :implicit # The sequece style used attr_accessor :style ### # Create a new object representing a YAML sequence. # # +anchor+ is the anchor associated with the sequence or nil. # +tag+ is the tag associated with the sequence or nil. # +implicit+ a boolean indicating whether or not the sequence was # implicitly started. # +style+ is an integer indicating the list style. # # See Psych::Handler#start_sequence def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK super() @anchor = anchor @tag = tag @implicit = implicit @style = style end end end end psych/nodes/node.rb000064400000002360147635151770010275 0ustar00require 'stringio' require 'psych/class_loader' require 'psych/scalar_scanner' module Psych module Nodes ### # The base class for any Node in a YAML parse tree. This class should # never be instantiated. class Node include Enumerable # The children of this node attr_reader :children # An associated tag attr_reader :tag # Create a new Psych::Nodes::Node def initialize @children = [] end ### # Iterate over each node in the tree. Yields each node to +block+ depth # first. def each &block return enum_for :each unless block_given? Visitors::DepthFirst.new(block).accept self end ### # Convert this node to Ruby. # # See also Psych::Visitors::ToRuby def to_ruby Visitors::ToRuby.create.accept(self) end alias :transform :to_ruby ### # Convert this node to YAML. # # See also Psych::Visitors::Emitter def yaml io = nil, options = {} real_io = io || StringIO.new(''.encode('utf-8')) Visitors::Emitter.new(real_io, options).accept self return real_io.string unless io io end alias :to_yaml :yaml end end end psych/nodes/alias.rb000064400000000720147635151770010437 0ustar00module Psych module Nodes ### # This class represents a {YAML Alias}[http://yaml.org/spec/1.1/#alias]. # It points to an +anchor+. # # A Psych::Nodes::Alias is a terminal node and may have no children. class Alias < Psych::Nodes::Node # The anchor this alias links to attr_accessor :anchor # Create a new Alias that points to an +anchor+ def initialize anchor @anchor = anchor end end end end psych/nodes/scalar.rb000064400000003107147635151770010615 0ustar00module Psych module Nodes ### # This class represents a {YAML Scalar}[http://yaml.org/spec/1.1/#id858081]. # # This node type is a terminal node and should not have any children. class Scalar < Psych::Nodes::Node # Any style scalar, the emitter chooses ANY = 0 # Plain scalar style PLAIN = 1 # Single quoted style SINGLE_QUOTED = 2 # Double quoted style DOUBLE_QUOTED = 3 # Literal style LITERAL = 4 # Folded style FOLDED = 5 # The scalar value attr_accessor :value # The anchor value (if there is one) attr_accessor :anchor # The tag value (if there is one) attr_accessor :tag # Is this a plain scalar? attr_accessor :plain # Is this scalar quoted? attr_accessor :quoted # The style of this scalar attr_accessor :style ### # Create a new Psych::Nodes::Scalar object. # # +value+ is the string value of the scalar # +anchor+ is an associated anchor or nil # +tag+ is an associated tag or nil # +plain+ is a boolean value # +quoted+ is a boolean value # +style+ is an integer idicating the string style # # == See Also # # See also Psych::Handler#scalar def initialize value, anchor = nil, tag = nil, plain = true, quoted = false, style = ANY @value = value @anchor = anchor @tag = tag @plain = plain @quoted = quoted @style = style end end end end psych/syntax_error.rb000064400000001053147635151770010775 0ustar00require 'psych/exception' module Psych class SyntaxError < Psych::Exception attr_reader :file, :line, :column, :offset, :problem, :context def initialize file, line, col, offset, problem, context err = [problem, context].compact.join ' ' filename = file || '' message = "(%s): %s at line %d column %d" % [filename, err, line, col] @file = file @line = line @column = col @offset = offset @problem = problem @context = context super(message) end end end psych/exception.rb000064400000000352147635151770010235 0ustar00module Psych class Exception < RuntimeError end class BadAlias < Exception end class DisallowedClass < Exception def initialize klass_name super "Tried to load unspecified class: #{klass_name}" end end end psych/deprecated.rb000064400000004767147635151770010355 0ustar00require 'date' module Psych DEPRECATED = __FILE__ # :nodoc: module DeprecatedMethods # :nodoc: attr_accessor :taguri attr_accessor :to_yaml_style end def self.quick_emit thing, opts = {}, &block # :nodoc: warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) target = eval 'self', block.binding target.extend DeprecatedMethods metaclass = class << target; self; end metaclass.send(:define_method, :encode_with) do |coder| target.taguri = coder.tag target.to_yaml_style = coder.style block.call coder end target.psych_to_yaml unless opts[:nodump] end # This method is deprecated, use Psych.load_stream instead. def self.load_documents yaml, &block if $VERBOSE warn "#{caller[0]}: load_documents is deprecated, use load_stream" end list = load_stream yaml return list unless block_given? list.each(&block) end def self.detect_implicit thing warn "#{caller[0]}: detect_implicit is deprecated" if $VERBOSE return '' unless String === thing return 'null' if '' == thing ss = ScalarScanner.new(ClassLoader.new) ss.tokenize(thing).class.name.downcase end def self.add_ruby_type type_tag, &block warn "#{caller[0]}: add_ruby_type is deprecated, use add_domain_type" if $VERBOSE domain = 'ruby.yaml.org,2002' key = ['tag', domain, type_tag].join ':' @domain_types[key] = [key, block] end def self.add_private_type type_tag, &block warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE domain = 'x-private' key = [domain, type_tag].join ':' @domain_types[key] = [key, block] end def self.tagurize thing warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE return thing unless String === thing "tag:yaml.org,2002:#{thing}" end def self.read_type_class type, reference warn "#{caller[0]}: read_type_class is deprecated" if $VERBOSE _, _, type, name = type.split ':', 4 reference = name.split('::').inject(reference) do |k,n| k.const_get(n.to_sym) end if name [type, reference] end def self.object_maker klass, hash warn "#{caller[0]}: object_maker is deprecated" if $VERBOSE klass.allocate.tap do |obj| hash.each { |k,v| obj.instance_variable_set(:"@#{k}", v) } end end end class Object undef :to_yaml_properties rescue nil def to_yaml_properties # :nodoc: instance_variables end end psych/json/stream.rb000064400000000570147635151770010505 0ustar00require 'psych/json/ruby_events' require 'psych/json/yaml_events' module Psych module JSON class Stream < Psych::Visitors::JSONTree include Psych::JSON::RubyEvents include Psych::Streaming extend Psych::Streaming::ClassMethods class Emitter < Psych::Stream::Emitter # :nodoc: include Psych::JSON::YAMLEvents end end end end psych/json/yaml_events.rb000064400000001355147635151770011542 0ustar00module Psych module JSON module YAMLEvents # :nodoc: def start_document version, tag_directives, implicit super(version, tag_directives, !streaming?) end def end_document implicit_end = !streaming? super(implicit_end) end def start_mapping anchor, tag, implicit, style super(anchor, nil, true, Nodes::Mapping::FLOW) end def start_sequence anchor, tag, implicit, style super(anchor, nil, true, Nodes::Sequence::FLOW) end def scalar value, anchor, tag, plain, quoted, style if "tag:yaml.org,2002:null" == tag super('null', nil, nil, true, false, Nodes::Scalar::PLAIN) else super end end end end end psych/json/ruby_events.rb000064400000000712147635151770011555 0ustar00module Psych module JSON module RubyEvents # :nodoc: def visit_Time o formatted = format_time o @emitter.scalar formatted, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED end def visit_DateTime o visit_Time o.to_time end def visit_String o @emitter.scalar o.to_s, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED end alias :visit_Symbol :visit_String end end end psych/json/tree_builder.rb000064400000000507147635151770011657 0ustar00require 'psych/json/yaml_events' module Psych module JSON ### # Psych::JSON::TreeBuilder is an event based AST builder. Events are sent # to an instance of Psych::JSON::TreeBuilder and a JSON AST is constructed. class TreeBuilder < Psych::TreeBuilder include Psych::JSON::YAMLEvents end end end psych/handlers/recorder.rb000064400000001527147635151770011651 0ustar00require 'psych/handler' module Psych module Handlers ### # This handler will capture an event and record the event. Recorder events # are available vial Psych::Handlers::Recorder#events. # # For example: # # recorder = Psych::Handlers::Recorder.new # parser = Psych::Parser.new recorder # parser.parse '--- foo' # # recorder.events # => [list of events] # # # Replay the events # # emitter = Psych::Emitter.new $stdout # recorder.events.each do |m, args| # emitter.send m, *args # end class Recorder < Psych::Handler attr_reader :events def initialize @events = [] super end EVENTS.each do |event| define_method event do |*args| @events << [event, args] end end end end end psych/handlers/document_stream.rb000064400000000750147635151770013232 0ustar00require 'psych/tree_builder' module Psych module Handlers class DocumentStream < Psych::TreeBuilder # :nodoc: def initialize &block super @block = block end def start_document version, tag_directives, implicit n = Nodes::Document.new version, tag_directives, implicit push n end def end_document implicit_end = !streaming? @last.implicit_end = implicit_end @block.call pop end end end end psych/class_loader.rb000064400000003605147635151770010676 0ustar00require 'psych/omap' require 'psych/set' module Psych class ClassLoader # :nodoc: BIG_DECIMAL = 'BigDecimal' COMPLEX = 'Complex' DATE = 'Date' DATE_TIME = 'DateTime' EXCEPTION = 'Exception' OBJECT = 'Object' PSYCH_OMAP = 'Psych::Omap' PSYCH_SET = 'Psych::Set' RANGE = 'Range' RATIONAL = 'Rational' REGEXP = 'Regexp' STRUCT = 'Struct' SYMBOL = 'Symbol' def initialize @cache = CACHE.dup end def load klassname return nil if !klassname || klassname.empty? find klassname end def symbolize sym symbol sym.to_sym end constants.each do |const| konst = const_get const define_method(const.to_s.downcase) do load konst end end private def find klassname @cache[klassname] ||= resolve(klassname) end def resolve klassname name = klassname retried = false begin path2class(name) rescue ArgumentError, NameError => ex unless retried name = "Struct::#{name}" retried = ex retry end raise retried end end CACHE = Hash[constants.map { |const| val = const_get const begin [val, ::Object.const_get(val)] rescue nil end }.compact] class Restricted < ClassLoader def initialize classes, symbols @classes = classes @symbols = symbols super() end def symbolize sym return super if @symbols.empty? if @symbols.include? sym super else raise DisallowedClass, 'Symbol' end end private def find klassname if @classes.include? klassname super else raise DisallowedClass, klassname end end end end end psych/visitors/depth_first.rb000064400000001124147635151770012432 0ustar00module Psych module Visitors class DepthFirst < Psych::Visitors::Visitor def initialize block @block = block end private def nary o o.children.each { |x| visit x } @block.call o end alias :visit_Psych_Nodes_Stream :nary alias :visit_Psych_Nodes_Document :nary alias :visit_Psych_Nodes_Sequence :nary alias :visit_Psych_Nodes_Mapping :nary def terminal o @block.call o end alias :visit_Psych_Nodes_Scalar :terminal alias :visit_Psych_Nodes_Alias :terminal end end end psych/visitors/to_ruby.rb000064400000024072147635151770011611 0ustar00require 'psych/scalar_scanner' require 'psych/class_loader' require 'psych/exception' unless defined?(Regexp::NOENCODING) Regexp::NOENCODING = 32 end module Psych module Visitors ### # This class walks a YAML AST, converting each node to ruby class ToRuby < Psych::Visitors::Visitor def self.create class_loader = ClassLoader.new scanner = ScalarScanner.new class_loader new(scanner, class_loader) end attr_reader :class_loader def initialize ss, class_loader super() @st = {} @ss = ss @domain_types = Psych.domain_types @class_loader = class_loader end def accept target result = super return result if @domain_types.empty? || !target.tag key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:') key = "tag:#{key}" unless key =~ /^(tag:|x-private)/ if @domain_types.key? key value, block = @domain_types[key] return block.call value, result end result end def deserialize o if klass = resolve_class(Psych.load_tags[o.tag]) instance = klass.allocate if instance.respond_to?(:init_with) coder = Psych::Coder.new(o.tag) coder.scalar = o.value instance.init_with coder end return instance end return o.value if o.quoted return @ss.tokenize(o.value) unless o.tag case o.tag when '!binary', 'tag:yaml.org,2002:binary' o.value.unpack('m').first when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str' klass = resolve_class($1) if klass klass.allocate.replace o.value else o.value end when '!ruby/object:BigDecimal' require 'bigdecimal' class_loader.big_decimal._load o.value when "!ruby/object:DateTime" class_loader.date_time require 'date' @ss.parse_time(o.value).to_datetime when "!ruby/object:Complex" class_loader.complex Complex(o.value) when "!ruby/object:Rational" class_loader.rational Rational(o.value) when "!ruby/class", "!ruby/module" resolve_class o.value when "tag:yaml.org,2002:float", "!float" Float(@ss.tokenize(o.value)) when "!ruby/regexp" klass = class_loader.regexp o.value =~ /^\/(.*)\/([mixn]*)$/ source = $1 options = 0 lang = nil ($2 || '').split('').each do |option| case option when 'x' then options |= Regexp::EXTENDED when 'i' then options |= Regexp::IGNORECASE when 'm' then options |= Regexp::MULTILINE when 'n' then options |= Regexp::NOENCODING else lang = option end end klass.new(*[source, options, lang].compact) when "!ruby/range" klass = class_loader.range args = o.value.split(/([.]{2,3})/, 2).map { |s| accept Nodes::Scalar.new(s) } args.push(args.delete_at(1) == '...') klass.new(*args) when /^!ruby\/sym(bol)?:?(.*)?$/ class_loader.symbolize o.value else @ss.tokenize o.value end end private :deserialize def visit_Psych_Nodes_Scalar o register o, deserialize(o) end def visit_Psych_Nodes_Sequence o if klass = resolve_class(Psych.load_tags[o.tag]) instance = klass.allocate if instance.respond_to?(:init_with) coder = Psych::Coder.new(o.tag) coder.seq = o.children.map { |c| accept c } instance.init_with coder end return instance end case o.tag when nil register_empty(o) when '!omap', 'tag:yaml.org,2002:omap' map = register(o, Psych::Omap.new) o.children.each { |a| map[accept(a.children.first)] = accept a.children.last } map when /^!(?:seq|ruby\/array):(.*)$/ klass = resolve_class($1) list = register(o, klass.allocate) o.children.each { |c| list.push accept c } list else register_empty(o) end end def visit_Psych_Nodes_Mapping o if Psych.load_tags[o.tag] return revive(resolve_class(Psych.load_tags[o.tag]), o) end return revive_hash({}, o) unless o.tag case o.tag when /^!ruby\/struct:?(.*)?$/ klass = resolve_class($1) if $1 if klass s = register(o, klass.allocate) members = {} struct_members = s.members.map { |x| class_loader.symbolize x } o.children.each_slice(2) do |k,v| member = accept(k) value = accept(v) if struct_members.include?(class_loader.symbolize(member)) s.send("#{member}=", value) else members[member.to_s.sub(/^@/, '')] = value end end init_with(s, members, o) else klass = class_loader.struct members = o.children.map { |c| accept c } h = Hash[*members] klass.new(*h.map { |k,v| class_loader.symbolize k }).new(*h.map { |k,v| v }) end when /^!ruby\/object:?(.*)?$/ name = $1 || 'Object' if name == 'Complex' class_loader.complex h = Hash[*o.children.map { |c| accept c }] register o, Complex(h['real'], h['image']) elsif name == 'Rational' class_loader.rational h = Hash[*o.children.map { |c| accept c }] register o, Rational(h['numerator'], h['denominator']) else obj = revive((resolve_class(name) || class_loader.object), o) obj end when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str' klass = resolve_class($1) members = Hash[*o.children.map { |c| accept c }] string = members.delete 'str' if klass string = klass.allocate.replace string register(o, string) end init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o) when /^!ruby\/array:(.*)$/ klass = resolve_class($1) list = register(o, klass.allocate) members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a] list.replace members['internal'] members['ivars'].each do |ivar, v| list.instance_variable_set ivar, v end list when '!ruby/range' klass = class_loader.range h = Hash[*o.children.map { |c| accept c }] register o, klass.new(h['begin'], h['end'], h['excl']) when /^!ruby\/exception:?(.*)?$/ h = Hash[*o.children.map { |c| accept c }] e = build_exception((resolve_class($1) || class_loader.exception), h.delete('message')) init_with(e, h, o) when '!set', 'tag:yaml.org,2002:set' set = class_loader.psych_set.new @st[o.anchor] = set if o.anchor o.children.each_slice(2) do |k,v| set[accept(k)] = accept(v) end set when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/ revive_hash resolve_class($1).new, o when '!omap', 'tag:yaml.org,2002:omap' map = register(o, class_loader.psych_omap.new) o.children.each_slice(2) do |l,r| map[accept(l)] = accept r end map else revive_hash({}, o) end end def visit_Psych_Nodes_Document o accept o.root end def visit_Psych_Nodes_Stream o o.children.map { |c| accept c } end def visit_Psych_Nodes_Alias o @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" } end private def register node, object @st[node.anchor] = object if node.anchor object end def register_empty object list = register(object, []) object.children.each { |c| list.push accept c } list end def revive_hash hash, o @st[o.anchor] = hash if o.anchor o.children.each_slice(2) { |k,v| key = accept(k) val = accept(v) if key == '<<' case v when Nodes::Alias begin hash.merge! val rescue TypeError hash[key] = val end when Nodes::Sequence begin h = {} val.reverse_each do |value| h.merge! value end hash.merge! h rescue TypeError hash[key] = val end else hash[key] = val end else hash[key] = val end } hash end def merge_key hash, key, val end def revive klass, node s = klass.allocate @st[node.anchor] = s if node.anchor h = Hash[*node.children.map { |c| accept c }] init_with(s, h, node) end def init_with o, h, node c = Psych::Coder.new(node.tag) c.map = h if o.respond_to?(:init_with) o.init_with c elsif o.respond_to?(:yaml_initialize) if $VERBOSE warn "Implementing #{o.class}#yaml_initialize is deprecated, please implement \"init_with(coder)\"" end o.yaml_initialize c.tag, c.map else h.each { |k,v| o.instance_variable_set(:"@#{k}", v) } end o end # Convert +klassname+ to a Class def resolve_class klassname class_loader.load klassname end end class NoAliasRuby < ToRuby def visit_Psych_Nodes_Alias o raise BadAlias, "Unknown alias: #{o.anchor}" end end end end psych/visitors/yaml_tree.rb000064400000033453147635151770012112 0ustar00require 'psych/tree_builder' require 'psych/scalar_scanner' require 'psych/class_loader' module Psych module Visitors ### # YAMLTree builds a YAML ast given a ruby object. For example: # # builder = Psych::Visitors::YAMLTree.new # builder << { :foo => 'bar' } # builder.tree # => # true) end end rescue # public_method or source_location might be overridden, # and it's OK to skip it since it's only to emit a warning end end if target.respond_to?(:encode_with) dump_coder target else send(@dispatch_cache[target.class], target) end end def visit_Psych_Omap o seq = @emitter.start_sequence(nil, '!omap', false, Nodes::Sequence::BLOCK) register(o, seq) o.each { |k,v| visit_Hash k => v } @emitter.end_sequence end def visit_Object o tag = Psych.dump_tags[o.class] unless tag klass = o.class == Object ? nil : o.class.name tag = ['!ruby/object', klass].compact.join(':') end map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) register(o, map) dump_ivars o @emitter.end_mapping end def visit_Struct o tag = ['!ruby/struct', o.class.name].compact.join(':') register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) o.members.each do |member| @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY accept o[member] end dump_ivars o @emitter.end_mapping end def visit_Exception o tag = ['!ruby/exception', o.class.name].join ':' @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK { 'message' => private_iv_get(o, 'mesg'), 'backtrace' => private_iv_get(o, 'backtrace'), }.each do |k,v| next unless v @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY accept v end dump_ivars o @emitter.end_mapping end def visit_Regexp o register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY) end def visit_DateTime o formatted = format_time o.to_time tag = '!ruby/object:DateTime' register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY) end def visit_Time o formatted = format_time o @emitter.scalar formatted, nil, nil, true, false, Nodes::Scalar::ANY end def visit_Rational o register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK) [ 'denominator', o.denominator.to_s, 'numerator', o.numerator.to_s ].each do |m| @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY end @emitter.end_mapping end def visit_Complex o register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK) ['real', o.real.to_s, 'image', o.imag.to_s].each do |m| @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY end @emitter.end_mapping end def visit_Integer o @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY end alias :visit_TrueClass :visit_Integer alias :visit_FalseClass :visit_Integer alias :visit_Date :visit_Integer def visit_Float o if o.nan? @emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY elsif o.infinite? @emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'), nil, nil, true, false, Nodes::Scalar::ANY) else @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY end end def visit_BigDecimal o @emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY end def binary? string (string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?) || string.index("\x00") || string.count("\x00-\x7F", "^ -~\t\r\n").fdiv(string.length) > 0.3 || string.class != String end private :binary? def visit_String o plain = true quote = true style = Nodes::Scalar::PLAIN tag = nil str = o if binary?(o) str = [o].pack('m').chomp tag = '!binary' # FIXME: change to below when syck is removed #tag = 'tag:yaml.org,2002:binary' style = Nodes::Scalar::LITERAL plain = false quote = false elsif o =~ /\n/ style = Nodes::Scalar::LITERAL else unless String === @ss.tokenize(o) style = Nodes::Scalar::SINGLE_QUOTED end end ivars = find_ivars o if ivars.empty? unless o.class == ::String tag = "!ruby/string:#{o.class}" end @emitter.scalar str, nil, tag, plain, quote, style else maptag = '!ruby/string' maptag << ":#{o.class}" unless o.class == ::String register o, @emitter.start_mapping(nil, maptag, false, Nodes::Mapping::BLOCK) @emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY @emitter.scalar str, nil, tag, plain, quote, style dump_ivars o @emitter.end_mapping end end def visit_Module o raise TypeError, "can't dump anonymous module: #{o}" unless o.name register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED) end def visit_Class o raise TypeError, "can't dump anonymous class: #{o}" unless o.name register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED) end def visit_Range o register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK) ['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m| accept m end @emitter.end_mapping end def visit_Hash o tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}" implicit = !tag register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| accept k accept v end @emitter.end_mapping end def visit_Psych_Set o register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| accept k accept v end @emitter.end_mapping end def visit_Array o if o.class == ::Array register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK) o.each { |c| accept c } @emitter.end_sequence else visit_array_subclass o end end def visit_NilClass o @emitter.scalar('', nil, 'tag:yaml.org,2002:null', true, false, Nodes::Scalar::ANY) end def visit_Symbol o @emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY end private def visit_array_subclass o tag = "!ruby/array:#{o.class}" if o.instance_variables.empty? node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK) register o, node o.each { |c| accept c } @emitter.end_sequence else node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK) register o, node # Dump the internal list accept 'internal' @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK) o.each { |c| accept c } @emitter.end_sequence # Dump the ivars accept 'ivars' @emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK) o.instance_variables.each do |ivar| accept ivar accept o.instance_variable_get ivar end @emitter.end_mapping @emitter.end_mapping end end def dump_list o end # '%:z' was no defined until 1.9.3 if RUBY_VERSION < '1.9.3' def format_time time formatted = time.strftime("%Y-%m-%d %H:%M:%S.%9N") if time.utc? formatted += " Z" else zone = time.strftime('%z') formatted += " #{zone[0,3]}:#{zone[3,5]}" end formatted end else def format_time time if time.utc? time.strftime("%Y-%m-%d %H:%M:%S.%9N Z") else time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z") end end end # FIXME: remove this method once "to_yaml_properties" is removed def find_ivars target begin loc = target.method(:to_yaml_properties).source_location.first unless loc.start_with?(Psych::DEPRECATED) || loc.end_with?('rubytypes.rb') if $VERBOSE warn "#{loc}: to_yaml_properties is deprecated, please implement \"encode_with(coder)\"" end return target.to_yaml_properties end rescue # public_method or source_location might be overridden, # and it's OK to skip it since it's only to emit a warning. end target.instance_variables end def register target, yaml_obj @st.register target, yaml_obj yaml_obj end def dump_coder o @coders << o tag = Psych.dump_tags[o.class] unless tag klass = o.class == Object ? nil : o.class.name tag = ['!ruby/object', klass].compact.join(':') end c = Psych::Coder.new(tag) o.encode_with(c) emit_coder c end def emit_coder c case c.type when :scalar @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY when :seq @emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK c.seq.each do |thing| accept thing end @emitter.end_sequence when :map @emitter.start_mapping nil, c.tag, c.implicit, c.style c.map.each do |k,v| @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY accept v end @emitter.end_mapping when :object accept c.object end end def dump_ivars target ivars = find_ivars target ivars.each do |iv| @emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY) accept target.instance_variable_get(iv) end end end end end psych/visitors/visitor.rb000064400000000511147635151770011615 0ustar00module Psych module Visitors class Visitor def accept target visit target end private DISPATCH = Hash.new do |hash, klass| hash[klass] = "visit_#{klass.name.gsub('::', '_')}" end def visit target send DISPATCH[target.class], target end end end end psych/visitors/emitter.rb000064400000002654147635151770011601 0ustar00module Psych module Visitors class Emitter < Psych::Visitors::Visitor def initialize io, options = {} opts = [:indentation, :canonical, :line_width].find_all { |opt| options.key?(opt) } if opts.empty? @handler = Psych::Emitter.new io else du = Handler::DumperOptions.new opts.each { |option| du.send :"#{option}=", options[option] } @handler = Psych::Emitter.new io, du end end def visit_Psych_Nodes_Stream o @handler.start_stream o.encoding o.children.each { |c| accept c } @handler.end_stream end def visit_Psych_Nodes_Document o @handler.start_document o.version, o.tag_directives, o.implicit o.children.each { |c| accept c } @handler.end_document o.implicit_end end def visit_Psych_Nodes_Scalar o @handler.scalar o.value, o.anchor, o.tag, o.plain, o.quoted, o.style end def visit_Psych_Nodes_Sequence o @handler.start_sequence o.anchor, o.tag, o.implicit, o.style o.children.each { |c| accept c } @handler.end_sequence end def visit_Psych_Nodes_Mapping o @handler.start_mapping o.anchor, o.tag, o.implicit, o.style o.children.each { |c| accept c } @handler.end_mapping end def visit_Psych_Nodes_Alias o @handler.alias o.anchor end end end end psych/visitors/json_tree.rb000064400000001055147635151770012112 0ustar00require 'psych/json/ruby_events' module Psych module Visitors class JSONTree < YAMLTree include Psych::JSON::RubyEvents def self.create options = {} emitter = Psych::JSON::TreeBuilder.new class_loader = ClassLoader.new ss = ScalarScanner.new class_loader new(emitter, ss, options) end def accept target if target.respond_to?(:encode_with) dump_coder target else send(@dispatch_cache[target.class], target) end end end end end psych/scalar_scanner.rb000064400000010264147635151770011220 0ustar00require 'strscan' module Psych ### # Scan scalars for built in types class ScalarScanner # Taken from http://yaml.org/type/timestamp.html TIME = /^\d{4}-\d{1,2}-\d{1,2}([Tt]|\s+)\d{1,2}:\d\d:\d\d(\.\d*)?(\s*Z|[-+]\d{1,2}(:\d\d)?)?/ # Taken from http://yaml.org/type/float.html FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10) |[-+]?[0-9][0-9_,]*(:[0-5]?[0-9])+\.[0-9_]*(?# base 60) |[-+]?\.(inf|Inf|INF)(?# infinity) |\.(nan|NaN|NAN)(?# not a number))$/x # Taken from http://yaml.org/type/int.html INTEGER = /^(?:[-+]?0b[0-1_]+ (?# base 2) |[-+]?0[0-7_]+ (?# base 8) |[-+]?(?:0|[1-9][0-9_]*) (?# base 10) |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x attr_reader :class_loader # Create a new scanner def initialize class_loader @string_cache = {} @symbol_cache = {} @class_loader = class_loader end # Tokenize +string+ returning the ruby object def tokenize string return nil if string.empty? return string if @string_cache.key?(string) return @symbol_cache[string] if @symbol_cache.key?(string) case string # Check for a String type, being careful not to get caught by hash keys, hex values, and # special floats (e.g., -.inf). when /^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/ if string.length > 5 @string_cache[string] = true return string end case string when /^[^ytonf~]/i @string_cache[string] = true string when '~', /^null$/i nil when /^(yes|true|on)$/i true when /^(no|false|off)$/i false else @string_cache[string] = true string end when TIME begin parse_time string rescue ArgumentError string end when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/ require 'date' begin class_loader.date.strptime(string, '%Y-%m-%d') rescue ArgumentError string end when /^\.inf$/i Float::INFINITY when /^-\.inf$/i -Float::INFINITY when /^\.nan$/i Float::NAN when /^:./ if string =~ /^:(["'])(.*)\1/ @symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, '')) else @symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, '')) end when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/ i = 0 string.split(':').each_with_index do |n,e| i += (n.to_i * 60 ** (e - 2).abs) end i when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/ i = 0 string.split(':').each_with_index do |n,e| i += (n.to_f * 60 ** (e - 2).abs) end i when FLOAT if string == '.' @string_cache[string] = true string else Float(string.gsub(/[,_]|\.$/, '')) end else int = parse_int string.gsub(/[,_]/, '') return int if int @string_cache[string] = true string end end ### # Parse and return an int from +string+ def parse_int string return unless INTEGER === string Integer(string) end ### # Parse and return a Time from +string+ def parse_time string klass = class_loader.load 'Time' date, time = *(string.split(/[ tT]/, 2)) (yy, m, dd) = date.split('-').map { |x| x.to_i } md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/) (hh, mm, ss) = md[1].split(':').map { |x| x.to_i } us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000 time = klass.utc(yy, m, dd, hh, mm, ss, us) return time if 'Z' == md[3] return klass.at(time.to_i, us) unless md[3] tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) } offset = tz.first * 3600 if offset < 0 offset -= ((tz[1] || 0) * 60) else offset += ((tz[1] || 0) * 60) end klass.at((time - offset).to_i, us) end end end psych/set.rb000064400000000054147635151770007031 0ustar00module Psych class Set < ::Hash end end psych/streaming.rb000064400000001175147635151770010234 0ustar00module Psych module Streaming module ClassMethods ### # Create a new streaming emitter. Emitter will print to +io+. See # Psych::Stream for an example. def new io emitter = const_get(:Emitter).new(io) class_loader = ClassLoader.new ss = ScalarScanner.new class_loader super(emitter, ss, {}) end end ### # Start streaming using +encoding+ def start encoding = Nodes::Stream::UTF8 super.tap { yield self if block_given? } ensure finish if block_given? end private def register target, obj end end end psych/coder.rb000064400000004024147635151770007333 0ustar00module Psych ### # If an object defines +encode_with+, then an instance of Psych::Coder will # be passed to the method when the object is being serialized. The Coder # automatically assumes a Psych::Nodes::Mapping is being emitted. Other # objects like Sequence and Scalar may be emitted if +seq=+ or +scalar=+ are # called, respectively. class Coder attr_accessor :tag, :style, :implicit, :object attr_reader :type, :seq def initialize tag @map = {} @seq = [] @implicit = false @type = :map @tag = tag @style = Psych::Nodes::Mapping::BLOCK @scalar = nil @object = nil end def scalar *args if args.length > 0 warn "#{caller[0]}: Coder#scalar(a,b,c) is deprecated" if $VERBOSE @tag, @scalar, _ = args @type = :scalar end @scalar end # Emit a map. The coder will be yielded to the block. def map tag = @tag, style = @style @tag = tag @style = style yield self if block_given? @map end # Emit a scalar with +value+ and +tag+ def represent_scalar tag, value self.tag = tag self.scalar = value end # Emit a sequence with +list+ and +tag+ def represent_seq tag, list @tag = tag self.seq = list end # Emit a sequence with +map+ and +tag+ def represent_map tag, map @tag = tag self.map = map end # Emit an arbitrary object +obj+ and +tag+ def represent_object tag, obj @tag = tag @type = :object @object = obj end # Emit a scalar with +value+ def scalar= value @type = :scalar @scalar = value end # Emit a map with +value+ def map= map @type = :map @map = map end def []= k, v @type = :map @map[k] = v end alias :add :[]= def [] k @type = :map @map[k] end # Emit a sequence of +list+ def seq= list @type = :seq @seq = list end end end psych/tree_builder.rb000064400000004070147635151770010705 0ustar00require 'psych/handler' module Psych ### # This class works in conjunction with Psych::Parser to build an in-memory # parse tree that represents a YAML document. # # == Example # # parser = Psych::Parser.new Psych::TreeBuilder.new # parser.parse('--- foo') # tree = parser.handler.root # # See Psych::Handler for documentation on the event methods used in this # class. class TreeBuilder < Psych::Handler # Returns the root node for the built tree attr_reader :root # Create a new TreeBuilder instance def initialize @stack = [] @last = nil @root = nil end %w{ Sequence Mapping }.each do |node| class_eval %{ def start_#{node.downcase}(anchor, tag, implicit, style) n = Nodes::#{node}.new(anchor, tag, implicit, style) @last.children << n push n end def end_#{node.downcase} pop end } end ### # Handles start_document events with +version+, +tag_directives+, # and +implicit+ styling. # # See Psych::Handler#start_document def start_document version, tag_directives, implicit n = Nodes::Document.new version, tag_directives, implicit @last.children << n push n end ### # Handles end_document events with +version+, +tag_directives+, # and +implicit+ styling. # # See Psych::Handler#start_document def end_document implicit_end = !streaming? @last.implicit_end = implicit_end pop end def start_stream encoding @root = Nodes::Stream.new(encoding) push @root end def end_stream pop end def scalar value, anchor, tag, plain, quoted, style s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style) @last.children << s s end def alias anchor @last.children << Nodes::Alias.new(anchor) end private def push value @stack.push value @last = value end def pop x = @stack.pop @last = @stack.last x end end end rdoc/meta_method.rb000064400000000143147635155430010321 0ustar00## # MetaMethod represents a meta-programmed method class RDoc::MetaMethod < RDoc::AnyMethod end rdoc/encoding.rb000064400000005372147635155430007632 0ustar00# coding: US-ASCII ## # This class is a wrapper around File IO and Encoding that helps RDoc load # files and convert them to the correct encoding. module RDoc::Encoding ## # Reads the contents of +filename+ and handles any encoding directives in # the file. # # The content will be converted to the +encoding+. If the file cannot be # converted a warning will be printed and nil will be returned. # # If +force_transcode+ is true the document will be transcoded and any # unknown character in the target encoding will be replaced with '?' def self.read_file filename, encoding, force_transcode = false content = open filename, "rb" do |f| f.read end content.gsub!("\r\n", "\n") if RUBY_PLATFORM =~ /mswin|mingw/ utf8 = content.sub!(/\A\xef\xbb\xbf/, '') RDoc::Encoding.set_encoding content if Object.const_defined? :Encoding then begin encoding ||= Encoding.default_external orig_encoding = content.encoding if utf8 then content.force_encoding Encoding::UTF_8 content.encode! encoding else # assume the content is in our output encoding content.force_encoding encoding end unless content.valid_encoding? then # revert and try to transcode content.force_encoding orig_encoding content.encode! encoding end unless content.valid_encoding? then warn "unable to convert #{filename} to #{encoding}, skipping" content = nil end rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError => e if force_transcode then content.force_encoding orig_encoding content.encode!(encoding, :invalid => :replace, :undef => :replace, :replace => '?') return content else warn "unable to convert #{e.message} for #{filename}, skipping" return nil end end end content rescue ArgumentError => e raise unless e.message =~ /unknown encoding name - (.*)/ warn "unknown encoding name \"#{$1}\" for #{filename}, skipping" nil rescue Errno::EISDIR, Errno::ENOENT nil end ## # Sets the encoding of +string+ based on the magic comment def self.set_encoding string string =~ /\A(?:#!.*\n)?(.*\n)/ first_line = $1 name = case first_line when /^<\?xml[^?]*encoding=(["'])(.*?)\1/ then $2 when /\b(?:en)?coding[=:]\s*([^\s;]+)/i then $1 else return end string.sub! first_line, '' return unless Object.const_defined? :Encoding enc = Encoding.find name string.force_encoding enc if enc end end rdoc/ri.rb000064400000000473147635155430006453 0ustar00require 'rdoc' ## # Namespace for the ri command line tool's implementation. # # See ri --help for details. module RDoc::RI ## # Base RI error class class Error < RDoc::Error; end autoload :Driver, 'rdoc/ri/driver' autoload :Paths, 'rdoc/ri/paths' autoload :Store, 'rdoc/ri/store' end rdoc/cross_reference.rb000064400000013476147635155430011217 0ustar00## # RDoc::CrossReference is a reusable way to create cross references for names. class RDoc::CrossReference ## # Regular expression to match class references # # 1. There can be a '\\' in front of text to suppress the cross-reference # 2. There can be a '::' in front of class names to reference from the # top-level namespace. # 3. The method can be followed by parenthesis (not recommended) CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)' ## # Regular expression to match method references. # # See CLASS_REGEXP_STR METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===)(?:\([\w.+*/=<>-]*\))?' ## # Regular expressions matching text that should potentially have # cross-reference links generated are passed to add_special. Note that # these expressions are meant to pick up text for which cross-references # have been suppressed, since the suppression characters are removed by the # code that is triggered. CROSSREF_REGEXP = /(?:^|\s) ( (?: # A::B::C.meth #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} # Stand-alone method (preceded by a #) | \\?\##{METHOD_REGEXP_STR} # Stand-alone method (preceded by ::) | ::#{METHOD_REGEXP_STR} # A::B::C # The stuff after CLASS_REGEXP_STR is a # nasty hack. CLASS_REGEXP_STR unfortunately matches # words like dog and cat (these are legal "class" # names in Fortran 95). When a word is flagged as a # potential cross-reference, limitations in the markup # engine suppress other processing, such as typesetting. # This is particularly noticeable for contractions. # In order that words like "can't" not # be flagged as potential cross-references, only # flag potential class cross-references if the character # after the cross-reference is a space, sentence # punctuation, tag start character, or attribute # marker. | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) # Things that look like filenames # The key thing is that there must be at least # one special character (period, slash, or # underscore). | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ # Things that have markup suppressed # Don't process things like '\<' in \, though. # TODO: including < is a hack, not very satisfying. | \\[^\s<] ) # labels for headings (?:@[\w+%-]+(?:\.[\w|%-]+)?)? )/x ## # Version of CROSSREF_REGEXP used when --hyperlink-all is specified. ALL_CROSSREF_REGEXP = / (?:^|\s) ( (?: # A::B::C.meth #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} # Stand-alone method | \\?#{METHOD_REGEXP_STR} # A::B::C | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) # Things that look like filenames | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ # Things that have markup suppressed | \\[^\s<] ) # labels for headings (?:@[\w+%-]+)? )/x ## # Hash of references that have been looked-up to their replacements attr_accessor :seen ## # Allows cross-references to be created based on the given +context+ # (RDoc::Context). def initialize context @context = context @store = context.store @seen = {} end ## # Returns a reference to +name+. # # If the reference is found and +name+ is not documented +text+ will be # returned. If +name+ is escaped +name+ is returned. If +name+ is not # found +text+ is returned. def resolve name, text return @seen[name] if @seen.include? name if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then type = $2 type = '' if type == '.' # will find either #method or ::method method = "#{type}#{$3}" container = @context.find_symbol_module($1) elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then type = $1 type = '' if type == '.' method = "#{type}#{$2}" container = @context else container = nil end if container then ref = container.find_local_symbol method unless ref || RDoc::TopLevel === container then ref = container.find_ancestor_local_symbol method end end ref = case name when /^\\(#{CLASS_REGEXP_STR})$/o then @context.find_symbol $1 else @context.find_symbol name end unless ref # Try a page name ref = @store.page name if not ref and name =~ /^\w+$/ ref = nil if RDoc::Alias === ref # external alias, can't link to it out = if name == '\\' then name elsif name =~ /^\\/ then # we remove the \ only in front of what we know: # other backslashes are treated later, only outside of ref ? $' : name elsif ref then if ref.display? then ref else text end else text end @seen[name] = out out end end rdoc/single_class.rb000064400000000512147635155430010501 0ustar00## # A singleton class class RDoc::SingleClass < RDoc::ClassModule ## # Adds the superclass to the included modules. def ancestors superclass ? super + [superclass] : super end ## # The definition of this singleton class, class << MyClassName def definition "class << #{full_name}" end end rdoc/rd/inline.rb000064400000002555147635155430007727 0ustar00## # Inline keeps track of markup and labels to create proper links. class RDoc::RD::Inline ## # The text of the reference attr_reader :reference ## # The markup of this reference in RDoc format attr_reader :rdoc ## # Creates a new Inline for +rdoc+ and +reference+. # # +rdoc+ may be another Inline or a String. If +reference+ is not given it # will use the text from +rdoc+. def self.new rdoc, reference = rdoc if self === rdoc and reference.equal? rdoc then rdoc else super end end ## # Initializes the Inline with +rdoc+ and +inline+ def initialize rdoc, reference # :not-new: @reference = reference.equal?(rdoc) ? reference.dup : reference # unpack @reference = @reference.reference if self.class === @reference @rdoc = rdoc end def == other # :nodoc: self.class === other and @reference == other.reference and @rdoc == other.rdoc end ## # Appends +more+ to this inline. +more+ may be a String or another Inline. def append more case more when String then @reference << more @rdoc << more when RDoc::RD::Inline then @reference << more.reference @rdoc << more.rdoc else raise "unknown thingy #{more}" end self end def inspect # :nodoc: "(inline: #{self})" end alias to_s rdoc # :nodoc: end rdoc/rd/block_parser.rb000064400000054265147635155430011124 0ustar00# # DO NOT MODIFY!!!! # This file is automatically generated by Racc 1.4.9 # from Racc grammer file "". # require 'racc/parser.rb' class RDoc::RD ## # RD format parser for headings, paragraphs, lists, verbatim sections that # exist as blocks. class BlockParser < Racc::Parser # :stopdoc: TMPFILE = ["rdtmp", $$, 0] MARK_TO_LEVEL = { '=' => 1, '==' => 2, '===' => 3, '====' => 4, '+' => 5, '++' => 6, } # :startdoc: ## # Footnotes for this document attr_reader :footnotes ## # Labels for items in this document attr_reader :labels ## # Path to find included files in attr_accessor :include_path ## # Creates a new RDoc::RD::BlockParser. Use #parse to parse an rd-format # document. def initialize @inline_parser = RDoc::RD::InlineParser.new self @include_path = [] # for testing @footnotes = [] @labels = {} end ## # Parses +src+ and returns an RDoc::Markup::Document. def parse src @src = src @src.push false @footnotes = [] @labels = {} # @i: index(line no.) of src @i = 0 # stack for current indentation @indent_stack = [] # how indented. @current_indent = @indent_stack.join("") # RDoc::RD::BlockParser for tmp src @subparser = nil # which part is in now @in_part = nil @part_content = [] @in_verbatim = false @yydebug = true document = do_parse unless @footnotes.empty? then blankline = document.parts.pop document.parts << RDoc::Markup::Rule.new(1) document.parts.concat @footnotes document.parts.push blankline end document end ## # Returns the next token from the document def next_token # :nodoc: # preprocessing # if it is not in RD part # => method while @in_part != "rd" line = @src[@i] @i += 1 # next line case line # src end when false return [false, false] # RD part begin when /^=begin\s*(?:\bRD\b.*)?\s*$/ if @in_part # if in non-RD part @part_content.push(line) else @in_part = "rd" return [:WHITELINE, "=begin\n"] # <= for textblockand end # non-RD part begin when /^=begin\s+(\w+)/ part = $1 if @in_part # if in non-RD part @part_content.push(line) else @in_part = part if @tree.filter[part] # if filter exists # p "BEGIN_PART: #{@in_part}" # DEBUG end # non-RD part end when /^=end/ if @in_part # if in non-RD part # p "END_PART: #{@in_part}" # DEBUG # make Part-in object part = RDoc::RD::Part.new(@part_content.join(""), @tree, "r") @part_content.clear # call filter, part_out is output(Part object) part_out = @tree.filter[@in_part].call(part) if @tree.filter[@in_part].mode == :rd # if output is RD formated subtree = parse_subtree(part_out.to_a) else # if output is target formated basename = TMPFILE.join('.') TMPFILE[-1] += 1 tmpfile = open(@tree.tmp_dir + "/" + basename + ".#{@in_part}", "w") tmpfile.print(part_out) tmpfile.close subtree = parse_subtree(["=begin\n", "<<< #{basename}\n", "=end\n"]) end @in_part = nil return [:SUBTREE, subtree] end else if @in_part # if in non-RD part @part_content.push(line) end end end @current_indent = @indent_stack.join("") line = @src[@i] case line when false if_current_indent_equal("") do [false, false] end when /^=end/ if_current_indent_equal("") do @in_part = nil [:WHITELINE, "=end"] # MUST CHANGE?? end when /^\s*$/ @i += 1 # next line return [:WHITELINE, ':WHITELINE'] when /^\#/ # comment line @i += 1 # next line self.next_token() when /^(={1,4})(?!=)\s*(?=\S)/, /^(\+{1,2})(?!\+)\s*(?=\S)/ rest = $' # ' rest.strip! mark = $1 if_current_indent_equal("") do return [:HEADLINE, [MARK_TO_LEVEL[mark], rest]] end when /^<<<\s*(\S+)/ file = $1 if_current_indent_equal("") do suffix = file[-3 .. -1] if suffix == ".rd" or suffix == ".rb" subtree = parse_subtree(get_included(file)) [:SUBTREE, subtree] else [:INCLUDE, file] end end when /^(\s*)\*(\s*)/ rest = $' # ' newIndent = $2 if_current_indent_equal($1) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s" << newIndent) [:ITEMLISTLINE, rest] end end when /^(\s*)(\(\d+\))(\s*)/ rest = $' # ' mark = $2 newIndent = $3 if_current_indent_equal($1) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s" * mark.size << newIndent) [:ENUMLISTLINE, rest] end end when /^(\s*):(\s*)/ rest = $' # ' newIndent = $2 if_current_indent_equal($1) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s#{$2}") [:DESCLISTLINE, rest] end end when /^(\s*)---(?!-|\s*$)/ indent = $1 rest = $' /\s*/ === rest term = $' new_indent = $& if_current_indent_equal(indent) do if @in_verbatim [:STRINGLINE, line] else @indent_stack.push("\s\s\s" + new_indent) [:METHODLISTLINE, term] end end when /^(\s*)/ if_current_indent_equal($1) do [:STRINGLINE, line] end else raise "[BUG] parsing error may occurred." end end ## # Yields to the given block if +indent+ matches the current indent, otherwise # an indentation token is processed. def if_current_indent_equal(indent) indent = indent.sub(/\t/, "\s" * 8) if @current_indent == indent @i += 1 # next line yield elsif indent.index(@current_indent) == 0 @indent_stack.push(indent[@current_indent.size .. -1]) [:INDENT, ":INDENT"] else @indent_stack.pop [:DEDENT, ":DEDENT"] end end private :if_current_indent_equal ## # Cuts off excess whitespace in +src+ def cut_off(src) ret = [] whiteline_buf = [] line = src.shift /^\s*/ =~ line indent = Regexp.quote($&) ret.push($') while line = src.shift if /^(\s*)$/ =~ line whiteline_buf.push(line) elsif /^#{indent}/ =~ line unless whiteline_buf.empty? ret.concat(whiteline_buf) whiteline_buf.clear end ret.push($') else raise "[BUG]: probably Parser Error while cutting off.\n" end end ret end private :cut_off def set_term_to_element(parent, term) # parent.set_term_under_document_struct(term, @tree.document_struct) parent.set_term_without_document_struct(term) end private :set_term_to_element ## # Raises a ParseError when invalid formatting is found def on_error(et, ev, _values) prv, cur, nxt = format_line_num(@i, @i+1, @i+2) raise ParseError, <|#{@src[@i].chomp} #{nxt} |#{@src[@i+1].chomp} Msg end ## # Current line number def line_index @i end ## # Parses subtree +src+ def parse_subtree src @subparser ||= RDoc::RD::BlockParser.new @subparser.parse src end private :parse_subtree ## # Retrieves the content for +file+ from the include_path def get_included(file) included = [] @include_path.each do |dir| file_name = File.join dir, file if File.exist? file_name then included = IO.readlines file_name break end end included end private :get_included ## # Formats line numbers +line_numbers+ prettily def format_line_num(*line_numbers) width = line_numbers.collect{|i| i.to_s.length }.max line_numbers.collect{|i| sprintf("%#{width}d", i) } end private :format_line_num ## # Retrieves the content of +values+ as a single String def content values values.map { |value| value.content }.join end ## # Creates a paragraph for +value+ def paragraph value content = cut_off(value).join(' ').rstrip contents = @inline_parser.parse content RDoc::Markup::Paragraph.new(*contents) end ## # Adds footnote +content+ to the document def add_footnote content index = @footnotes.length / 2 + 1 footmark_link = "{^#{index}}[rdoc-label:footmark-#{index}:foottext-#{index}]" @footnotes << RDoc::Markup::Paragraph.new(footmark_link, ' ', *content) @footnotes << RDoc::Markup::BlankLine.new index end ## # Adds label +label+ to the document def add_label label @labels[label] = true label end # :stopdoc: ##### State transition tables begin ### racc_action_table = [ 34, 35, 30, 33, 14, 73, 38, 33, 76, 15, 88, 34, 35, 30, 33, 40, 34, 35, 30, 33, 40, 65, 34, 35, 30, 33, 14, 73, 77, 14, 54, 15, 34, 35, 30, 33, 14, 9, 10, 11, 12, 15, 34, 35, 30, 33, 14, 73, 81, 54, 38, 15, 34, 35, 30, 33, 14, 73, 40, 67, 83, 15, 34, 35, 30, 33, 14, 73, 54, 30, 35, 15, 34, 35, 30, 33, 34, 47, 36, 14, 59, 15, 34, 35, 30, 33, 14, 73, 38, nil, nil, 15, 34, 35, 30, 33, nil, 47, nil, nil, nil, 15, 34, 35, 30, 33, 14, 73, nil, nil, nil, 15, 34, 35, 30, 33, 14, 73, nil, nil, nil, 15, 34, 35, 30, 33, 14, 9, 10, 11, 12, 15, 34, 35, 30, 33, 14, 73, nil, nil, nil, 15, 34, 35, 30, 33, 14, 73, 61, 63, nil, 15, nil, 62, 60, 61, 63, 61, 63, 14, 62, 87, 62, nil, 79, 34, 35, 30, 33 ] racc_action_check = [ 86, 86, 86, 86, 86, 86, 57, 31, 49, 86, 86, 41, 41, 41, 41, 41, 15, 15, 15, 15, 15, 41, 45, 45, 45, 45, 45, 45, 51, 34, 54, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85, 85, 85, 56, 33, 58, 85, 79, 79, 79, 79, 79, 79, 62, 44, 66, 79, 78, 78, 78, 78, 78, 78, 30, 28, 25, 78, 24, 24, 24, 24, 22, 24, 1, 35, 36, 24, 75, 75, 75, 75, 75, 75, 13, nil, nil, 75, 27, 27, 27, 27, nil, 27, nil, nil, nil, 27, 74, 74, 74, 74, 74, 74, nil, nil, nil, 74, 68, 68, 68, 68, 68, 68, nil, nil, nil, 68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, nil, nil, nil, 46, 47, 47, 47, 47, 47, 47, 39, 39, nil, 47, nil, 39, 39, 82, 82, 64, 64, 52, 82, 82, 64, nil, 52, 20, 20, 20, 20 ] racc_action_pointer = [ 29, 78, 119, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 81, nil, 13, nil, nil, nil, nil, 162, nil, 73, nil, 69, 66, nil, 89, 64, nil, 60, 1, nil, 41, 22, 72, 80, nil, nil, 141, nil, 8, nil, nil, 46, 19, 129, 139, nil, -5, nil, 15, 152, nil, 22, nil, 35, -1, 43, nil, nil, nil, 51, nil, 150, nil, 47, nil, 109, nil, nil, nil, nil, nil, 99, 79, nil, nil, 59, 49, nil, nil, 148, nil, nil, 39, -3, nil, nil ] racc_action_default = [ -2, -73, -1, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -16, -73, -23, -24, -25, -26, -27, -31, -32, -34, -72, -36, -38, -72, -40, -42, -59, -44, -46, -59, -63, -65, -73, -3, -15, -73, -22, -73, -30, -33, -73, -69, -70, -71, -37, -73, -41, -73, -51, -58, -61, -45, -73, -62, -64, 89, -17, -19, -73, -21, -18, -28, -73, -35, -66, -53, -54, -55, -56, -57, -67, -68, -39, -43, -49, -73, -60, -47, -73, -29, -52, -48, -73, -20, -50 ] racc_goto_table = [ 4, 39, 4, 68, 74, 75, 5, 6, 5, 6, 51, 42, 44, 56, 3, 49, 37, 57, 58, 41, 43, 48, 84, 50, 66, 55, 1, 64, 84, 84, 45, 46, 42, 45, 46, 2, 85, 86, 80, 84, 84, nil, nil, nil, nil, nil, nil, nil, 82, nil, nil, nil, 78 ] racc_goto_check = [ 4, 10, 4, 31, 31, 31, 5, 6, 5, 6, 27, 12, 21, 27, 3, 21, 3, 9, 9, 17, 19, 23, 32, 26, 11, 29, 1, 10, 32, 32, 5, 6, 12, 5, 6, 2, 31, 31, 33, 32, 32, nil, nil, nil, nil, nil, nil, nil, 10, nil, nil, nil, 4 ] racc_goto_pointer = [ nil, 26, 35, 14, 0, 6, 7, nil, nil, -17, -14, -17, -9, nil, nil, nil, nil, 4, nil, -2, nil, -12, nil, -4, nil, nil, -5, -20, nil, -6, nil, -42, -46, -16 ] racc_goto_default = [ nil, nil, nil, nil, 70, 71, 72, 7, 8, 13, nil, nil, 21, 16, 17, 18, 19, 20, 22, 23, 24, nil, 25, 26, 27, 28, 29, nil, 31, 32, 52, nil, 69, 53 ] racc_reduce_table = [ 0, 0, :racc_error, 1, 15, :_reduce_1, 0, 15, :_reduce_2, 2, 16, :_reduce_3, 1, 16, :_reduce_4, 1, 17, :_reduce_5, 1, 17, :_reduce_6, 1, 17, :_reduce_none, 1, 17, :_reduce_8, 1, 17, :_reduce_9, 1, 17, :_reduce_10, 1, 17, :_reduce_11, 1, 21, :_reduce_12, 1, 22, :_reduce_13, 1, 18, :_reduce_14, 2, 23, :_reduce_15, 1, 23, :_reduce_16, 3, 19, :_reduce_17, 1, 25, :_reduce_18, 2, 24, :_reduce_19, 4, 24, :_reduce_20, 2, 24, :_reduce_21, 1, 24, :_reduce_22, 1, 26, :_reduce_none, 1, 26, :_reduce_none, 1, 26, :_reduce_none, 1, 26, :_reduce_none, 1, 20, :_reduce_27, 3, 20, :_reduce_28, 4, 20, :_reduce_29, 2, 31, :_reduce_30, 1, 31, :_reduce_31, 1, 27, :_reduce_32, 2, 32, :_reduce_33, 1, 32, :_reduce_34, 3, 33, :_reduce_35, 1, 28, :_reduce_36, 2, 36, :_reduce_37, 1, 36, :_reduce_38, 3, 37, :_reduce_39, 1, 29, :_reduce_40, 2, 39, :_reduce_41, 1, 39, :_reduce_42, 3, 40, :_reduce_43, 1, 30, :_reduce_44, 2, 42, :_reduce_45, 1, 42, :_reduce_46, 3, 43, :_reduce_47, 3, 41, :_reduce_48, 2, 41, :_reduce_49, 4, 41, :_reduce_50, 1, 41, :_reduce_51, 2, 45, :_reduce_52, 1, 45, :_reduce_none, 1, 46, :_reduce_54, 1, 46, :_reduce_55, 1, 46, :_reduce_none, 1, 46, :_reduce_57, 1, 44, :_reduce_none, 0, 44, :_reduce_none, 2, 47, :_reduce_none, 1, 47, :_reduce_none, 2, 34, :_reduce_62, 1, 34, :_reduce_63, 2, 38, :_reduce_64, 1, 38, :_reduce_65, 2, 35, :_reduce_66, 2, 35, :_reduce_67, 2, 35, :_reduce_68, 1, 35, :_reduce_69, 1, 35, :_reduce_none, 1, 35, :_reduce_71, 0, 35, :_reduce_72 ] racc_reduce_n = 73 racc_shift_n = 89 racc_token_table = { false => 0, :error => 1, :DUMMY => 2, :ITEMLISTLINE => 3, :ENUMLISTLINE => 4, :DESCLISTLINE => 5, :METHODLISTLINE => 6, :STRINGLINE => 7, :WHITELINE => 8, :SUBTREE => 9, :HEADLINE => 10, :INCLUDE => 11, :INDENT => 12, :DEDENT => 13 } racc_nt_base = 14 racc_use_result_var = true Racc_arg = [ racc_action_table, racc_action_check, racc_action_default, racc_action_pointer, racc_goto_table, racc_goto_check, racc_goto_default, racc_goto_pointer, racc_nt_base, racc_reduce_table, racc_token_table, racc_shift_n, racc_reduce_n, racc_use_result_var ] Racc_token_to_s_table = [ "$end", "error", "DUMMY", "ITEMLISTLINE", "ENUMLISTLINE", "DESCLISTLINE", "METHODLISTLINE", "STRINGLINE", "WHITELINE", "SUBTREE", "HEADLINE", "INCLUDE", "INDENT", "DEDENT", "$start", "document", "blocks", "block", "textblock", "verbatim", "lists", "headline", "include", "textblockcontent", "verbatimcontent", "verbatim_after_lists", "list", "itemlist", "enumlist", "desclist", "methodlist", "lists2", "itemlistitems", "itemlistitem", "first_textblock_in_itemlist", "other_blocks_in_list", "enumlistitems", "enumlistitem", "first_textblock_in_enumlist", "desclistitems", "desclistitem", "description_part", "methodlistitems", "methodlistitem", "whitelines", "blocks_in_list", "block_in_list", "whitelines2" ] Racc_debug_parser = false ##### State transition tables end ##### # reduce 0 omitted def _reduce_1(val, _values, result) result = RDoc::Markup::Document.new(*val[0]) result end def _reduce_2(val, _values, result) raise ParseError, "file empty" result end def _reduce_3(val, _values, result) result = val[0].concat val[1] result end def _reduce_4(val, _values, result) result = val[0] result end def _reduce_5(val, _values, result) result = val result end def _reduce_6(val, _values, result) result = val result end # reduce 7 omitted def _reduce_8(val, _values, result) result = val result end def _reduce_9(val, _values, result) result = val result end def _reduce_10(val, _values, result) result = [RDoc::Markup::BlankLine.new] result end def _reduce_11(val, _values, result) result = val[0].parts result end def _reduce_12(val, _values, result) # val[0] is like [level, title] title = @inline_parser.parse(val[0][1]) result = RDoc::Markup::Heading.new(val[0][0], title) result end def _reduce_13(val, _values, result) result = RDoc::Markup::Include.new val[0], @include_path result end def _reduce_14(val, _values, result) # val[0] is Array of String result = paragraph val[0] result end def _reduce_15(val, _values, result) result << val[1].rstrip result end def _reduce_16(val, _values, result) result = [val[0].rstrip] result end def _reduce_17(val, _values, result) # val[1] is Array of String content = cut_off val[1] result = RDoc::Markup::Verbatim.new(*content) # imform to lexer. @in_verbatim = false result end def _reduce_18(val, _values, result) # val[0] is Array of String content = cut_off val[0] result = RDoc::Markup::Verbatim.new(*content) # imform to lexer. @in_verbatim = false result end def _reduce_19(val, _values, result) result << val[1] result end def _reduce_20(val, _values, result) result.concat val[2] result end def _reduce_21(val, _values, result) result << "\n" result end def _reduce_22(val, _values, result) result = val # inform to lexer. @in_verbatim = true result end # reduce 23 omitted # reduce 24 omitted # reduce 25 omitted # reduce 26 omitted def _reduce_27(val, _values, result) result = val[0] result end def _reduce_28(val, _values, result) result = val[1] result end def _reduce_29(val, _values, result) result = val[1].push(val[2]) result end def _reduce_30(val, _values, result) result = val[0] << val[1] result end def _reduce_31(val, _values, result) result = [val[0]] result end def _reduce_32(val, _values, result) result = RDoc::Markup::List.new :BULLET, *val[0] result end def _reduce_33(val, _values, result) result.push(val[1]) result end def _reduce_34(val, _values, result) result = val result end def _reduce_35(val, _values, result) result = RDoc::Markup::ListItem.new nil, val[0], *val[1] result end def _reduce_36(val, _values, result) result = RDoc::Markup::List.new :NUMBER, *val[0] result end def _reduce_37(val, _values, result) result.push(val[1]) result end def _reduce_38(val, _values, result) result = val result end def _reduce_39(val, _values, result) result = RDoc::Markup::ListItem.new nil, val[0], *val[1] result end def _reduce_40(val, _values, result) result = RDoc::Markup::List.new :NOTE, *val[0] result end def _reduce_41(val, _values, result) result.push(val[1]) result end def _reduce_42(val, _values, result) result = val result end def _reduce_43(val, _values, result) term = @inline_parser.parse val[0].strip result = RDoc::Markup::ListItem.new term, *val[1] result end def _reduce_44(val, _values, result) result = RDoc::Markup::List.new :LABEL, *val[0] result end def _reduce_45(val, _values, result) result.push(val[1]) result end def _reduce_46(val, _values, result) result = val result end def _reduce_47(val, _values, result) result = RDoc::Markup::ListItem.new "#{val[0].strip}", *val[1] result end def _reduce_48(val, _values, result) result = [val[1]].concat(val[2]) result end def _reduce_49(val, _values, result) result = [val[1]] result end def _reduce_50(val, _values, result) result = val[2] result end def _reduce_51(val, _values, result) result = [] result end def _reduce_52(val, _values, result) result.concat val[1] result end # reduce 53 omitted def _reduce_54(val, _values, result) result = val result end def _reduce_55(val, _values, result) result = val result end # reduce 56 omitted def _reduce_57(val, _values, result) result = [] result end # reduce 58 omitted # reduce 59 omitted # reduce 60 omitted # reduce 61 omitted def _reduce_62(val, _values, result) result = paragraph [val[0]].concat(val[1]) result end def _reduce_63(val, _values, result) result = paragraph [val[0]] result end def _reduce_64(val, _values, result) result = paragraph [val[0]].concat(val[1]) result end def _reduce_65(val, _values, result) result = paragraph [val[0]] result end def _reduce_66(val, _values, result) result = [val[0]].concat(val[1]) result end def _reduce_67(val, _values, result) result.concat val[1] result end def _reduce_68(val, _values, result) result = val[1] result end def _reduce_69(val, _values, result) result = val result end # reduce 70 omitted def _reduce_71(val, _values, result) result = [] result end def _reduce_72(val, _values, result) result = [] result end def _reduce_none(val, _values, result) val[0] end end # class BlockParser end rdoc/rd/inline_parser.rb000064400000076550147635155430011311 0ustar00# # DO NOT MODIFY!!!! # This file is automatically generated by Racc 1.4.9 # from Racc grammer file "". # require 'racc/parser.rb' require 'strscan' class RDoc::RD ## # RD format parser for inline markup such as emphasis, links, footnotes, etc. class InlineParser < Racc::Parser # :stopdoc: EM_OPEN = '((*' EM_OPEN_RE = /\A#{Regexp.quote(EM_OPEN)}/ EM_CLOSE = '*))' EM_CLOSE_RE = /\A#{Regexp.quote(EM_CLOSE)}/ CODE_OPEN = '(({' CODE_OPEN_RE = /\A#{Regexp.quote(CODE_OPEN)}/ CODE_CLOSE = '}))' CODE_CLOSE_RE = /\A#{Regexp.quote(CODE_CLOSE)}/ VAR_OPEN = '((|' VAR_OPEN_RE = /\A#{Regexp.quote(VAR_OPEN)}/ VAR_CLOSE = '|))' VAR_CLOSE_RE = /\A#{Regexp.quote(VAR_CLOSE)}/ KBD_OPEN = '((%' KBD_OPEN_RE = /\A#{Regexp.quote(KBD_OPEN)}/ KBD_CLOSE = '%))' KBD_CLOSE_RE = /\A#{Regexp.quote(KBD_CLOSE)}/ INDEX_OPEN = '((:' INDEX_OPEN_RE = /\A#{Regexp.quote(INDEX_OPEN)}/ INDEX_CLOSE = ':))' INDEX_CLOSE_RE = /\A#{Regexp.quote(INDEX_CLOSE)}/ REF_OPEN = '((<' REF_OPEN_RE = /\A#{Regexp.quote(REF_OPEN)}/ REF_CLOSE = '>))' REF_CLOSE_RE = /\A#{Regexp.quote(REF_CLOSE)}/ FOOTNOTE_OPEN = '((-' FOOTNOTE_OPEN_RE = /\A#{Regexp.quote(FOOTNOTE_OPEN)}/ FOOTNOTE_CLOSE = '-))' FOOTNOTE_CLOSE_RE = /\A#{Regexp.quote(FOOTNOTE_CLOSE)}/ VERB_OPEN = "(('" VERB_OPEN_RE = /\A#{Regexp.quote(VERB_OPEN)}/ VERB_CLOSE = "'))" VERB_CLOSE_RE = /\A#{Regexp.quote(VERB_CLOSE)}/ BAR = "|" BAR_RE = /\A#{Regexp.quote(BAR)}/ QUOTE = '"' QUOTE_RE = /\A#{Regexp.quote(QUOTE)}/ SLASH = "/" SLASH_RE = /\A#{Regexp.quote(SLASH)}/ BACK_SLASH = "\\" BACK_SLASH_RE = /\A#{Regexp.quote(BACK_SLASH)}/ URL = "URL:" URL_RE = /\A#{Regexp.quote(URL)}/ other_re_mode = Regexp::EXTENDED other_re_mode |= Regexp::MULTILINE OTHER_RE = Regexp.new( "\\A.+?(?=#{Regexp.quote(EM_OPEN)}|#{Regexp.quote(EM_CLOSE)}| #{Regexp.quote(CODE_OPEN)}|#{Regexp.quote(CODE_CLOSE)}| #{Regexp.quote(VAR_OPEN)}|#{Regexp.quote(VAR_CLOSE)}| #{Regexp.quote(KBD_OPEN)}|#{Regexp.quote(KBD_CLOSE)}| #{Regexp.quote(INDEX_OPEN)}|#{Regexp.quote(INDEX_CLOSE)}| #{Regexp.quote(REF_OPEN)}|#{Regexp.quote(REF_CLOSE)}| #{Regexp.quote(FOOTNOTE_OPEN)}|#{Regexp.quote(FOOTNOTE_CLOSE)}| #{Regexp.quote(VERB_OPEN)}|#{Regexp.quote(VERB_CLOSE)}| #{Regexp.quote(BAR)}| #{Regexp.quote(QUOTE)}| #{Regexp.quote(SLASH)}| #{Regexp.quote(BACK_SLASH)}| #{Regexp.quote(URL)})", other_re_mode) # :startdoc: ## # Creates a new parser for inline markup in the rd format. The +block_parser+ # is used to for footnotes and labels in the inline text. def initialize block_parser @block_parser = block_parser end ## # Parses the +inline+ text from RD format into RDoc format. def parse inline @inline = inline @src = StringScanner.new inline @pre = "" @yydebug = true do_parse.to_s end ## # Returns the next token from the inline text def next_token return [false, false] if @src.eos? # p @src.rest if @yydebug if ret = @src.scan(EM_OPEN_RE) @pre << ret [:EM_OPEN, ret] elsif ret = @src.scan(EM_CLOSE_RE) @pre << ret [:EM_CLOSE, ret] elsif ret = @src.scan(CODE_OPEN_RE) @pre << ret [:CODE_OPEN, ret] elsif ret = @src.scan(CODE_CLOSE_RE) @pre << ret [:CODE_CLOSE, ret] elsif ret = @src.scan(VAR_OPEN_RE) @pre << ret [:VAR_OPEN, ret] elsif ret = @src.scan(VAR_CLOSE_RE) @pre << ret [:VAR_CLOSE, ret] elsif ret = @src.scan(KBD_OPEN_RE) @pre << ret [:KBD_OPEN, ret] elsif ret = @src.scan(KBD_CLOSE_RE) @pre << ret [:KBD_CLOSE, ret] elsif ret = @src.scan(INDEX_OPEN_RE) @pre << ret [:INDEX_OPEN, ret] elsif ret = @src.scan(INDEX_CLOSE_RE) @pre << ret [:INDEX_CLOSE, ret] elsif ret = @src.scan(REF_OPEN_RE) @pre << ret [:REF_OPEN, ret] elsif ret = @src.scan(REF_CLOSE_RE) @pre << ret [:REF_CLOSE, ret] elsif ret = @src.scan(FOOTNOTE_OPEN_RE) @pre << ret [:FOOTNOTE_OPEN, ret] elsif ret = @src.scan(FOOTNOTE_CLOSE_RE) @pre << ret [:FOOTNOTE_CLOSE, ret] elsif ret = @src.scan(VERB_OPEN_RE) @pre << ret [:VERB_OPEN, ret] elsif ret = @src.scan(VERB_CLOSE_RE) @pre << ret [:VERB_CLOSE, ret] elsif ret = @src.scan(BAR_RE) @pre << ret [:BAR, ret] elsif ret = @src.scan(QUOTE_RE) @pre << ret [:QUOTE, ret] elsif ret = @src.scan(SLASH_RE) @pre << ret [:SLASH, ret] elsif ret = @src.scan(BACK_SLASH_RE) @pre << ret [:BACK_SLASH, ret] elsif ret = @src.scan(URL_RE) @pre << ret [:URL, ret] elsif ret = @src.scan(OTHER_RE) @pre << ret [:OTHER, ret] else ret = @src.rest @pre << ret @src.terminate [:OTHER, ret] end end ## # Raises a ParseError when invalid formatting is found def on_error(et, ev, values) lines_of_rest = @src.rest.lines.to_a.length prev_words = prev_words_on_error(ev) at = 4 + prev_words.length message = <<-MSG RD syntax error: line #{@block_parser.line_index - lines_of_rest}: ...#{prev_words} #{(ev||'')} #{next_words_on_error()} ... MSG message << " " * at + "^" * (ev ? ev.length : 0) + "\n" raise ParseError, message end ## # Returns words before the error def prev_words_on_error(ev) pre = @pre if ev and /#{Regexp.quote(ev)}$/ =~ pre pre = $` end last_line(pre) end ## # Returns the last line of +src+ def last_line(src) if n = src.rindex("\n") src[(n+1) .. -1] else src end end private :last_line ## # Returns words following an error def next_words_on_error if n = @src.rest.index("\n") @src.rest[0 .. (n-1)] else @src.rest end end ## # Creates a new RDoc::RD::Inline for the +rdoc+ markup and the raw +reference+ def inline rdoc, reference = rdoc RDoc::RD::Inline.new rdoc, reference end # :stopdoc: ##### State transition tables begin ### racc_action_table = [ 63, 64, 65, 153, 81, 62, 76, 78, 79, 87, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 80, 152, 63, 64, 65, 61, 81, 62, 76, 78, 79, 124, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 80, 149, 104, 103, 102, 100, 101, 99, 115, 116, 117, 164, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 96, 118, 119, 104, 103, 102, 100, 101, 99, 115, 116, 117, 89, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 88, 118, 119, 104, 103, 102, 100, 101, 99, 115, 116, 117, 161, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 86, 118, 119, 104, 103, 102, 100, 101, 99, 115, 116, 117, 85, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 137, 118, 119, 63, 64, 65, 61, 81, 62, 76, 78, 79, 84, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 80, 22, 23, 24, 25, 26, 21, 18, 19, 176, 177, 13, 173, 14, 154, 15, 175, 16, 137, 17, 42, 148, 20, 54, 38, 53, 55, 56, 57, 29, 13, 177, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, 145, nil, 20, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, 122, 17, nil, 54, 20, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 22, 23, 24, 25, 26, 21, 18, 19, nil, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 135, 136, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 135, 136, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 135, 136, 54, 133, 53, 55, 56, 57, nil, 13, nil, 14, nil, 15, nil, 16, nil, 17, nil, nil, 20, 172, 135, 136, 54, 133, 53, 55, 56, 57, 165, 135, 136, 54, 133, 53, 55, 56, 57, 95, nil, nil, 54, 91, 53, 55, 56, 57, 174, 135, 136, 54, 133, 53, 55, 56, 57, 158, nil, nil, 54, nil, 53, 55, 56, 57, 178, 135, 136, 54, 133, 53, 55, 56, 57, 145, nil, nil, 54, 133, 53, 55, 56, 57, 145, nil, nil, 54, 133, 53, 55, 56, 57, 135, 136, 54, 133, 53, 55, 56, 57, 135, 136, 54, 133, 53, 55, 56, 57, 135, 136, 54, 133, 53, 55, 56, 57, 22, 23, 24, 25, 26, 21 ] racc_action_check = [ 61, 61, 61, 61, 61, 61, 61, 61, 61, 33, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 41, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 97, 97, 97, 97, 97, 97, 97, 97, 97, 125, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 37, 97, 97, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 34, 38, 38, 155, 155, 155, 155, 155, 155, 155, 155, 155, 100, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 32, 155, 155, 91, 91, 91, 91, 91, 91, 91, 91, 91, 31, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 43, 91, 91, 20, 20, 20, 20, 20, 20, 20, 20, 20, 29, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 17, 17, 17, 17, 17, 17, 17, 17, 165, 165, 17, 162, 17, 90, 17, 164, 17, 94, 17, 18, 58, 17, 18, 18, 18, 18, 18, 18, 1, 18, 172, 18, nil, 18, nil, 18, nil, 18, nil, nil, 18, 19, 19, 19, 19, 19, 19, 19, 19, nil, nil, 19, nil, 19, nil, 19, nil, 19, nil, 19, nil, nil, 19, 16, 16, 16, 16, 16, 16, 16, 16, nil, nil, 16, nil, 16, nil, 16, nil, 16, nil, 16, nil, nil, 16, 15, 15, 15, 15, 15, 15, 15, 15, nil, nil, 15, nil, 15, nil, 15, nil, 15, nil, 15, 45, nil, 15, 45, 45, 45, 45, 45, 45, nil, 45, nil, 45, nil, 45, nil, 45, nil, 45, nil, nil, 45, 14, 14, 14, 14, 14, 14, 14, 14, nil, nil, 14, nil, 14, nil, 14, nil, 14, nil, 14, 146, nil, 14, 146, 146, 146, 146, 146, 146, nil, 146, nil, 146, nil, 146, nil, 146, nil, 146, nil, nil, 146, 13, 13, 13, 13, 13, 13, 13, 13, nil, nil, 13, nil, 13, nil, 13, nil, 13, nil, 13, 138, nil, 13, 138, 138, 138, 138, 138, 138, nil, 138, nil, 138, nil, 138, nil, 138, nil, 138, 44, nil, 138, 44, 44, 44, 44, 44, 44, nil, 44, nil, 44, nil, 44, nil, 44, nil, 44, nil, nil, 44, 2, 2, 2, 2, 2, 2, 2, 2, nil, nil, 2, nil, 2, nil, 2, nil, 2, 39, 2, nil, 39, 2, 39, 39, 39, 39, nil, 39, nil, 39, nil, 39, nil, 39, nil, 39, nil, nil, 39, 0, 0, 0, 0, 0, 0, 0, 0, nil, nil, 0, nil, 0, nil, 0, nil, 0, nil, 0, nil, nil, 0, 122, 122, 122, 122, 122, 122, 122, 122, nil, 122, nil, 122, nil, 122, nil, 122, nil, 122, nil, nil, 122, 127, 127, 127, 127, 127, 127, 127, 127, nil, 127, nil, 127, nil, 127, nil, 127, nil, 127, nil, nil, 127, 42, 42, 42, 42, 42, 42, 42, 42, nil, 42, nil, 42, nil, 42, nil, 42, nil, 42, nil, nil, 42, 159, 159, 159, 159, 159, 159, 159, 159, 159, 126, 126, 126, 126, 126, 126, 126, 126, 126, 36, nil, nil, 36, 36, 36, 36, 36, 36, 163, 163, 163, 163, 163, 163, 163, 163, 163, 92, nil, nil, 92, nil, 92, 92, 92, 92, 171, 171, 171, 171, 171, 171, 171, 171, 171, 142, nil, nil, 142, 142, 142, 142, 142, 142, 52, nil, nil, 52, 52, 52, 52, 52, 52, 95, 95, 95, 95, 95, 95, 95, 95, 168, 168, 168, 168, 168, 168, 168, 168, 158, 158, 158, 158, 158, 158, 158, 158, 27, 27, 27, 27, 27, 27 ] racc_action_pointer = [ 423, 188, 384, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 324, 283, 242, 220, 157, 176, 198, 135, nil, nil, nil, nil, nil, nil, 604, nil, 147, nil, 110, 96, -9, 69, 56, 526, 43, 66, 401, nil, 28, 486, 130, 362, 261, nil, nil, nil, nil, nil, nil, 571, nil, nil, nil, nil, nil, 169, 20, nil, -3, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 150, 112, 544, nil, 172, 579, nil, 43, nil, nil, 95, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 444, nil, nil, 52, 517, 465, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 343, nil, nil, nil, 562, nil, nil, nil, 302, nil, nil, nil, nil, nil, nil, nil, nil, 89, nil, nil, 595, 508, nil, nil, 168, 535, 171, 164, nil, nil, 587, nil, nil, 553, 185, nil, nil, nil, nil, nil, nil ] racc_action_default = [ -138, -138, -1, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -138, -138, -138, -138, -138, -138, -138, -138, -103, -104, -105, -106, -107, -108, -111, -110, -138, -2, -138, -138, -138, -138, -138, -138, -138, -138, -27, -26, -35, -138, -58, -41, -40, -47, -48, -49, -50, -51, -52, -63, -66, -67, -68, -69, -70, -138, -138, -112, -138, -116, -117, -118, -119, -120, -121, -122, -123, -124, -125, -126, -127, -128, -129, -130, -131, -132, -133, -134, -135, -137, -109, 179, -13, -14, -15, -16, -17, -138, -138, -23, -22, -33, -138, -19, -24, -79, -80, -138, -82, -83, -84, -85, -86, -87, -88, -89, -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, -100, -25, -35, -138, -58, -28, -138, -59, -42, -46, -55, -56, -65, -71, -72, -75, -76, -77, -31, -38, -44, -53, -54, -57, -61, -73, -74, -39, -62, -101, -102, -136, -113, -114, -115, -18, -20, -21, -33, -138, -138, -78, -81, -138, -59, -36, -37, -64, -45, -59, -43, -60, -138, -34, -36, -37, -29, -30, -32, -34 ] racc_goto_table = [ 126, 44, 125, 43, 144, 144, 160, 93, 97, 52, 166, 82, 144, 41, 40, 39, 138, 146, 169, 147, 167, 94, 44, 1, 123, 129, 169, 52, 36, 37, 52, 90, 59, 92, 121, 120, 31, 32, 33, 34, 35, 170, 58, 166, 83, 30, 170, 166, 151, nil, 150, nil, 166, 159, 8, 166, 8, nil, nil, nil, nil, 155, nil, 156, 160, nil, nil, 8, 8, 8, 8, 8, nil, 8, 4, nil, 4, 157, nil, nil, 163, nil, 162, 52, nil, 168, nil, 4, 4, 4, 4, 4, nil, 4, nil, nil, nil, nil, 144, nil, nil, nil, 144, nil, nil, 129, 144, 144, nil, 5, 129, 5, nil, nil, nil, nil, 171, 6, nil, 6, nil, nil, 5, 5, 5, 5, 5, 11, 5, 11, 6, 6, 6, 6, 6, 7, 6, 7, nil, nil, 11, 11, 11, 11, 11, nil, 11, nil, 7, 7, 7, 7, 7, nil, 7 ] racc_goto_check = [ 22, 24, 21, 23, 36, 36, 37, 18, 16, 34, 35, 41, 36, 20, 19, 17, 25, 25, 28, 32, 29, 23, 24, 1, 23, 24, 28, 34, 13, 15, 34, 14, 38, 17, 20, 19, 1, 1, 1, 1, 1, 33, 1, 35, 39, 3, 33, 35, 42, nil, 41, nil, 35, 22, 8, 35, 8, nil, nil, nil, nil, 16, nil, 18, 37, nil, nil, 8, 8, 8, 8, 8, nil, 8, 4, nil, 4, 23, nil, nil, 22, nil, 21, 34, nil, 22, nil, 4, 4, 4, 4, 4, nil, 4, nil, nil, nil, nil, 36, nil, nil, nil, 36, nil, nil, 24, 36, 36, nil, 5, 24, 5, nil, nil, nil, nil, 22, 6, nil, 6, nil, nil, 5, 5, 5, 5, 5, 11, 5, 11, 6, 6, 6, 6, 6, 7, 6, 7, nil, nil, 11, 11, 11, 11, 11, nil, 11, nil, 7, 7, 7, 7, 7, nil, 7 ] racc_goto_pointer = [ nil, 23, nil, 43, 74, 109, 117, 135, 54, nil, nil, 127, nil, 10, -5, 11, -30, -3, -29, -4, -5, -40, -42, -15, -17, -28, nil, nil, -120, -107, nil, nil, -33, -101, -9, -116, -40, -91, 12, 17, nil, -9, -13 ] racc_goto_default = [ nil, nil, 2, 3, 46, 47, 48, 49, 50, 9, 10, 51, 12, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 140, nil, 45, 127, 139, 128, 141, 130, 142, 143, 132, 131, 134, 98, nil, 28, 27, nil, 60 ] racc_reduce_table = [ 0, 0, :racc_error, 1, 27, :_reduce_none, 2, 28, :_reduce_2, 1, 28, :_reduce_3, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 1, 29, :_reduce_none, 3, 30, :_reduce_13, 3, 31, :_reduce_14, 3, 32, :_reduce_15, 3, 33, :_reduce_16, 3, 34, :_reduce_17, 4, 35, :_reduce_18, 3, 35, :_reduce_19, 2, 40, :_reduce_20, 2, 40, :_reduce_21, 1, 40, :_reduce_22, 1, 40, :_reduce_23, 2, 41, :_reduce_24, 2, 41, :_reduce_25, 1, 41, :_reduce_26, 1, 41, :_reduce_27, 2, 39, :_reduce_none, 4, 39, :_reduce_29, 4, 39, :_reduce_30, 2, 43, :_reduce_31, 4, 43, :_reduce_32, 1, 44, :_reduce_33, 3, 44, :_reduce_34, 1, 45, :_reduce_none, 3, 45, :_reduce_36, 3, 45, :_reduce_37, 2, 46, :_reduce_38, 2, 46, :_reduce_39, 1, 46, :_reduce_40, 1, 46, :_reduce_41, 1, 47, :_reduce_none, 2, 51, :_reduce_43, 1, 51, :_reduce_44, 2, 53, :_reduce_45, 1, 53, :_reduce_46, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 50, :_reduce_none, 1, 54, :_reduce_none, 1, 54, :_reduce_none, 1, 55, :_reduce_none, 1, 55, :_reduce_none, 1, 56, :_reduce_57, 1, 52, :_reduce_58, 1, 57, :_reduce_59, 2, 58, :_reduce_60, 1, 58, :_reduce_none, 2, 49, :_reduce_62, 1, 49, :_reduce_none, 2, 48, :_reduce_64, 1, 48, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 62, :_reduce_none, 1, 62, :_reduce_none, 1, 59, :_reduce_none, 1, 59, :_reduce_none, 1, 61, :_reduce_none, 1, 61, :_reduce_none, 1, 61, :_reduce_none, 2, 42, :_reduce_78, 1, 42, :_reduce_none, 1, 63, :_reduce_none, 2, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 1, 63, :_reduce_none, 3, 36, :_reduce_101, 3, 37, :_reduce_102, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 1, 65, :_reduce_none, 2, 66, :_reduce_109, 1, 66, :_reduce_none, 1, 38, :_reduce_111, 1, 67, :_reduce_none, 2, 67, :_reduce_113, 2, 67, :_reduce_114, 2, 67, :_reduce_115, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 1, 68, :_reduce_none, 2, 64, :_reduce_136, 1, 64, :_reduce_none ] racc_reduce_n = 138 racc_shift_n = 179 racc_token_table = { false => 0, :error => 1, :EX_LOW => 2, :QUOTE => 3, :BAR => 4, :SLASH => 5, :BACK_SLASH => 6, :URL => 7, :OTHER => 8, :REF_OPEN => 9, :FOOTNOTE_OPEN => 10, :FOOTNOTE_CLOSE => 11, :EX_HIGH => 12, :EM_OPEN => 13, :EM_CLOSE => 14, :CODE_OPEN => 15, :CODE_CLOSE => 16, :VAR_OPEN => 17, :VAR_CLOSE => 18, :KBD_OPEN => 19, :KBD_CLOSE => 20, :INDEX_OPEN => 21, :INDEX_CLOSE => 22, :REF_CLOSE => 23, :VERB_OPEN => 24, :VERB_CLOSE => 25 } racc_nt_base = 26 racc_use_result_var = true Racc_arg = [ racc_action_table, racc_action_check, racc_action_default, racc_action_pointer, racc_goto_table, racc_goto_check, racc_goto_default, racc_goto_pointer, racc_nt_base, racc_reduce_table, racc_token_table, racc_shift_n, racc_reduce_n, racc_use_result_var ] Racc_token_to_s_table = [ "$end", "error", "EX_LOW", "QUOTE", "BAR", "SLASH", "BACK_SLASH", "URL", "OTHER", "REF_OPEN", "FOOTNOTE_OPEN", "FOOTNOTE_CLOSE", "EX_HIGH", "EM_OPEN", "EM_CLOSE", "CODE_OPEN", "CODE_CLOSE", "VAR_OPEN", "VAR_CLOSE", "KBD_OPEN", "KBD_CLOSE", "INDEX_OPEN", "INDEX_CLOSE", "REF_CLOSE", "VERB_OPEN", "VERB_CLOSE", "$start", "content", "elements", "element", "emphasis", "code", "var", "keyboard", "index", "reference", "footnote", "verb", "normal_str_ele", "substitute", "ref_label", "ref_label2", "ref_url_strings", "filename", "element_label", "element_label2", "ref_subst_content", "ref_subst_content_q", "ref_subst_strings_q", "ref_subst_strings_first", "ref_subst_ele2", "ref_subst_eles", "ref_subst_str_ele_first", "ref_subst_eles_q", "ref_subst_ele", "ref_subst_ele_q", "ref_subst_str_ele", "ref_subst_str_ele_q", "ref_subst_strings", "ref_subst_string3", "ref_subst_string", "ref_subst_string_q", "ref_subst_string2", "ref_url_string", "verb_strings", "normal_string", "normal_strings", "verb_string", "verb_normal_string" ] Racc_debug_parser = false ##### State transition tables end ##### # reduce 0 omitted # reduce 1 omitted def _reduce_2(val, _values, result) result.append val[1] result end def _reduce_3(val, _values, result) result = val[0] result end # reduce 4 omitted # reduce 5 omitted # reduce 6 omitted # reduce 7 omitted # reduce 8 omitted # reduce 9 omitted # reduce 10 omitted # reduce 11 omitted # reduce 12 omitted def _reduce_13(val, _values, result) content = val[1] result = inline "#{content}", content result end def _reduce_14(val, _values, result) content = val[1] result = inline "#{content}", content result end def _reduce_15(val, _values, result) content = val[1] result = inline "+#{content}+", content result end def _reduce_16(val, _values, result) content = val[1] result = inline "#{content}", content result end def _reduce_17(val, _values, result) label = val[1] @block_parser.add_label label.reference result = "#{label}" result end def _reduce_18(val, _values, result) result = "{#{val[1]}}[#{val[2].join}]" result end def _reduce_19(val, _values, result) scheme, inline = val[1] result = "{#{inline}}[#{scheme}#{inline.reference}]" result end def _reduce_20(val, _values, result) result = [nil, inline(val[1])] result end def _reduce_21(val, _values, result) result = [ 'rdoc-label:', inline("#{val[0].reference}/#{val[1].reference}") ] result end def _reduce_22(val, _values, result) result = ['rdoc-label:', val[0].reference] result end def _reduce_23(val, _values, result) result = ['rdoc-label:', "#{val[0].reference}/"] result end def _reduce_24(val, _values, result) result = [nil, inline(val[1])] result end def _reduce_25(val, _values, result) result = [ 'rdoc-label:', inline("#{val[0].reference}/#{val[1].reference}") ] result end def _reduce_26(val, _values, result) result = ['rdoc-label:', val[0]] result end def _reduce_27(val, _values, result) ref = val[0].reference result = ['rdoc-label:', inline(ref, "#{ref}/")] result end # reduce 28 omitted def _reduce_29(val, _values, result) result = val[1] result end def _reduce_30(val, _values, result) result = val[1] result end def _reduce_31(val, _values, result) result = inline val[0] result end def _reduce_32(val, _values, result) result = inline "\"#{val[1]}\"" result end def _reduce_33(val, _values, result) result = inline val[0] result end def _reduce_34(val, _values, result) result = inline "\"#{val[1]}\"" result end # reduce 35 omitted def _reduce_36(val, _values, result) result = val[1] result end def _reduce_37(val, _values, result) result = inline val[1] result end def _reduce_38(val, _values, result) result = val[0].append val[1] result end def _reduce_39(val, _values, result) result = val[0].append val[1] result end def _reduce_40(val, _values, result) result = val[0] result end def _reduce_41(val, _values, result) result = inline val[0] result end # reduce 42 omitted def _reduce_43(val, _values, result) result = val[0].append val[1] result end def _reduce_44(val, _values, result) result = inline val[0] result end def _reduce_45(val, _values, result) result = val[0].append val[1] result end def _reduce_46(val, _values, result) result = val[0] result end # reduce 47 omitted # reduce 48 omitted # reduce 49 omitted # reduce 50 omitted # reduce 51 omitted # reduce 52 omitted # reduce 53 omitted # reduce 54 omitted # reduce 55 omitted # reduce 56 omitted def _reduce_57(val, _values, result) result = val[0] result end def _reduce_58(val, _values, result) result = inline val[0] result end def _reduce_59(val, _values, result) result = inline val[0] result end def _reduce_60(val, _values, result) result << val[1] result end # reduce 61 omitted def _reduce_62(val, _values, result) result << val[1] result end # reduce 63 omitted def _reduce_64(val, _values, result) result << val[1] result end # reduce 65 omitted # reduce 66 omitted # reduce 67 omitted # reduce 68 omitted # reduce 69 omitted # reduce 70 omitted # reduce 71 omitted # reduce 72 omitted # reduce 73 omitted # reduce 74 omitted # reduce 75 omitted # reduce 76 omitted # reduce 77 omitted def _reduce_78(val, _values, result) result << val[1] result end # reduce 79 omitted # reduce 80 omitted # reduce 81 omitted # reduce 82 omitted # reduce 83 omitted # reduce 84 omitted # reduce 85 omitted # reduce 86 omitted # reduce 87 omitted # reduce 88 omitted # reduce 89 omitted # reduce 90 omitted # reduce 91 omitted # reduce 92 omitted # reduce 93 omitted # reduce 94 omitted # reduce 95 omitted # reduce 96 omitted # reduce 97 omitted # reduce 98 omitted # reduce 99 omitted # reduce 100 omitted def _reduce_101(val, _values, result) index = @block_parser.add_footnote val[1].rdoc result = "{*#{index}}[rdoc-label:foottext-#{index}:footmark-#{index}]" result end def _reduce_102(val, _values, result) result = inline "#{val[1]}", val[1] result end # reduce 103 omitted # reduce 104 omitted # reduce 105 omitted # reduce 106 omitted # reduce 107 omitted # reduce 108 omitted def _reduce_109(val, _values, result) result << val[1] result end # reduce 110 omitted def _reduce_111(val, _values, result) result = inline val[0] result end # reduce 112 omitted def _reduce_113(val, _values, result) result = val[1] result end def _reduce_114(val, _values, result) result = val[1] result end def _reduce_115(val, _values, result) result = val[1] result end # reduce 116 omitted # reduce 117 omitted # reduce 118 omitted # reduce 119 omitted # reduce 120 omitted # reduce 121 omitted # reduce 122 omitted # reduce 123 omitted # reduce 124 omitted # reduce 125 omitted # reduce 126 omitted # reduce 127 omitted # reduce 128 omitted # reduce 129 omitted # reduce 130 omitted # reduce 131 omitted # reduce 132 omitted # reduce 133 omitted # reduce 134 omitted # reduce 135 omitted def _reduce_136(val, _values, result) result << val[1] result end # reduce 137 omitted def _reduce_none(val, _values, result) val[0] end end # class InlineParser end rdoc/class_module.rb000064400000046231147635155430010515 0ustar00## # ClassModule is the base class for objects representing either a class or a # module. class RDoc::ClassModule < RDoc::Context ## # 1:: # RDoc 3.7 # * Added visibility, singleton and file to attributes # * Added file to constants # * Added file to includes # * Added file to methods # 2:: # RDoc 3.13 # * Added extends # 3:: # RDoc 4.0 # * Added sections # * Added in_files # * Added parent name # * Complete Constant dump MARSHAL_VERSION = 3 # :nodoc: ## # Constants that are aliases for this class or module attr_accessor :constant_aliases ## # Comment and the location it came from. Use #add_comment to add comments attr_accessor :comment_location attr_accessor :diagram # :nodoc: ## # Class or module this constant is an alias for attr_accessor :is_alias_for ## # Return a RDoc::ClassModule of class +class_type+ that is a copy # of module +module+. Used to promote modules to classes. #-- # TODO move to RDoc::NormalClass (I think) def self.from_module class_type, mod klass = class_type.new mod.name mod.comment_location.each do |comment, location| klass.add_comment comment, location end klass.parent = mod.parent klass.section = mod.section klass.viewer = mod.viewer klass.attributes.concat mod.attributes klass.method_list.concat mod.method_list klass.aliases.concat mod.aliases klass.external_aliases.concat mod.external_aliases klass.constants.concat mod.constants klass.includes.concat mod.includes klass.extends.concat mod.extends klass.methods_hash.update mod.methods_hash klass.constants_hash.update mod.constants_hash klass.current_section = mod.current_section klass.in_files.concat mod.in_files klass.sections.concat mod.sections klass.unmatched_alias_lists = mod.unmatched_alias_lists klass.current_section = mod.current_section klass.visibility = mod.visibility klass.classes_hash.update mod.classes_hash klass.modules_hash.update mod.modules_hash klass.metadata.update mod.metadata klass.document_self = mod.received_nodoc ? nil : mod.document_self klass.document_children = mod.document_children klass.force_documentation = mod.force_documentation klass.done_documenting = mod.done_documenting # update the parent of all children (klass.attributes + klass.method_list + klass.aliases + klass.external_aliases + klass.constants + klass.includes + klass.extends + klass.classes + klass.modules).each do |obj| obj.parent = klass obj.full_name = nil end klass end ## # Creates a new ClassModule with +name+ with optional +superclass+ # # This is a constructor for subclasses, and must never be called directly. def initialize(name, superclass = nil) @constant_aliases = [] @diagram = nil @is_alias_for = nil @name = name @superclass = superclass @comment_location = [] # [[comment, location]] super() end ## # Adds +comment+ to this ClassModule's list of comments at +location+. This # method is preferred over #comment= since it allows ri data to be updated # across multiple runs. def add_comment comment, location return unless document_self original = comment comment = case comment when RDoc::Comment then comment.normalize else normalize_comment comment end @comment_location.delete_if { |(_, l)| l == location } @comment_location << [comment, location] self.comment = original end def add_things my_things, other_things # :nodoc: other_things.each do |group, things| my_things[group].each { |thing| yield false, thing } if my_things.include? group things.each do |thing| yield true, thing end end end ## # Ancestors list for this ClassModule: the list of included modules # (classes will add their superclass if any). # # Returns the included classes or modules, not the includes # themselves. The returned values are either String or # RDoc::NormalModule instances (see RDoc::Include#module). # # The values are returned in reverse order of their inclusion, # which is the order suitable for searching methods/attributes # in the ancestors. The superclass, if any, comes last. def ancestors includes.map { |i| i.module }.reverse end ## # Ancestors of this class or module only alias direct_ancestors ancestors ## # Clears the comment. Used by the ruby parser. def clear_comment @comment = '' end ## # This method is deprecated, use #add_comment instead. # # Appends +comment+ to the current comment, but separated by a rule. Works # more like +=. def comment= comment # :nodoc: comment = case comment when RDoc::Comment then comment.normalize else normalize_comment comment end comment = "#{@comment}\n---\n#{comment}" unless @comment.empty? super comment end ## # Prepares this ClassModule for use by a generator. # # See RDoc::Store#complete def complete min_visibility update_aliases remove_nodoc_children update_includes remove_invisible min_visibility end ## # Does this ClassModule or any of its methods have document_self set? def document_self_or_methods document_self || method_list.any?{ |m| m.document_self } end ## # Does this class or module have a comment with content or is # #received_nodoc true? def documented? super or !@comment_location.empty? end ## # Iterates the ancestors of this class or module for which an # RDoc::ClassModule exists. def each_ancestor # :yields: module return enum_for __method__ unless block_given? ancestors.each do |mod| next if String === mod next if self == mod yield mod end end ## # Looks for a symbol in the #ancestors. See Context#find_local_symbol. def find_ancestor_local_symbol symbol each_ancestor do |m| res = m.find_local_symbol(symbol) return res if res end nil end ## # Finds a class or module with +name+ in this namespace or its descendants def find_class_named name return self if full_name == name return self if @name == name @classes.values.find do |klass| next if klass == self klass.find_class_named name end end ## # Return the fully qualified name of this class or module def full_name @full_name ||= if RDoc::ClassModule === parent then "#{parent.full_name}::#{@name}" else @name end end ## # TODO: filter included items by #display? def marshal_dump # :nodoc: attrs = attributes.sort.map do |attr| [ attr.name, attr.rw, attr.visibility, attr.singleton, attr.file_name, ] end method_types = methods_by_type.map do |type, visibilities| visibilities = visibilities.map do |visibility, methods| method_names = methods.map do |method| [method.name, method.file_name] end [visibility, method_names.uniq] end [type, visibilities] end [ MARSHAL_VERSION, @name, full_name, @superclass, parse(@comment_location), attrs, constants, includes.map do |incl| [incl.name, parse(incl.comment), incl.file_name] end, method_types, extends.map do |ext| [ext.name, parse(ext.comment), ext.file_name] end, @sections.values, @in_files.map do |tl| tl.relative_name end, parent.full_name, parent.class, ] end def marshal_load array # :nodoc: initialize_visibility initialize_methods_etc @current_section = nil @document_self = true @done_documenting = false @parent = nil @temporary_section = nil @visibility = nil @classes = {} @modules = {} @name = array[1] @full_name = array[2] @superclass = array[3] @comment = array[4] @comment_location = if RDoc::Markup::Document === @comment.parts.first then @comment else RDoc::Markup::Document.new @comment end array[5].each do |name, rw, visibility, singleton, file| singleton ||= false visibility ||= :public attr = RDoc::Attr.new nil, name, rw, nil, singleton add_attribute attr attr.visibility = visibility attr.record_location RDoc::TopLevel.new file end array[6].each do |constant, comment, file| case constant when RDoc::Constant then add_constant constant else constant = add_constant RDoc::Constant.new(constant, nil, comment) constant.record_location RDoc::TopLevel.new file end end array[7].each do |name, comment, file| incl = add_include RDoc::Include.new(name, comment) incl.record_location RDoc::TopLevel.new file end array[8].each do |type, visibilities| visibilities.each do |visibility, methods| @visibility = visibility methods.each do |name, file| method = RDoc::AnyMethod.new nil, name method.singleton = true if type == 'class' method.record_location RDoc::TopLevel.new file add_method method end end end array[9].each do |name, comment, file| ext = add_extend RDoc::Extend.new(name, comment) ext.record_location RDoc::TopLevel.new file end if array[9] # Support Marshal version 1 sections = (array[10] || []).map do |section| [section.title, section] end @sections = Hash[*sections.flatten] @current_section = add_section nil @in_files = [] (array[11] || []).each do |filename| record_location RDoc::TopLevel.new filename end @parent_name = array[12] @parent_class = array[13] end ## # Merges +class_module+ into this ClassModule. # # The data in +class_module+ is preferred over the receiver. def merge class_module @parent = class_module.parent @parent_name = class_module.parent_name other_document = parse class_module.comment_location if other_document then document = parse @comment_location document = document.merge other_document @comment = @comment_location = document end cm = class_module other_files = cm.in_files merge_collections attributes, cm.attributes, other_files do |add, attr| if add then add_attribute attr else @attributes.delete attr @methods_hash.delete attr.pretty_name end end merge_collections constants, cm.constants, other_files do |add, const| if add then add_constant const else @constants.delete const @constants_hash.delete const.name end end merge_collections includes, cm.includes, other_files do |add, incl| if add then add_include incl else @includes.delete incl end end @includes.uniq! # clean up merge_collections extends, cm.extends, other_files do |add, ext| if add then add_extend ext else @extends.delete ext end end @extends.uniq! # clean up merge_collections method_list, cm.method_list, other_files do |add, meth| if add then add_method meth else @method_list.delete meth @methods_hash.delete meth.pretty_name end end merge_sections cm self end ## # Merges collection +mine+ with +other+ preferring other. +other_files+ is # used to help determine which items should be deleted. # # Yields whether the item should be added or removed (true or false) and the # item to be added or removed. # # merge_collections things, other.things, other.in_files do |add, thing| # if add then # # add the thing # else # # remove the thing # end # end def merge_collections mine, other, other_files, &block # :nodoc: my_things = mine. group_by { |thing| thing.file } other_things = other.group_by { |thing| thing.file } remove_things my_things, other_files, &block add_things my_things, other_things, &block end ## # Merges the comments in this ClassModule with the comments in the other # ClassModule +cm+. def merge_sections cm # :nodoc: my_sections = sections.group_by { |section| section.title } other_sections = cm.sections.group_by { |section| section.title } other_files = cm.in_files remove_things my_sections, other_files do |_, section| @sections.delete section.title end other_sections.each do |group, sections| if my_sections.include? group my_sections[group].each do |my_section| other_section = cm.sections_hash[group] my_comments = my_section.comments other_comments = other_section.comments other_files = other_section.in_files merge_collections my_comments, other_comments, other_files do |add, comment| if add then my_section.add_comment comment else my_section.remove_comment comment end end end else sections.each do |section| add_section group, section.comments end end end end ## # Does this object represent a module? def module? false end ## # Allows overriding the initial name. # # Used for modules and classes that are constant aliases. def name= new_name @name = new_name end ## # Parses +comment_location+ into an RDoc::Markup::Document composed of # multiple RDoc::Markup::Documents with their file set. def parse comment_location case comment_location when String then super when Array then docs = comment_location.map do |comment, location| doc = super comment doc.file = location doc end RDoc::Markup::Document.new(*docs) when RDoc::Comment then doc = super comment_location.text, comment_location.format doc.file = comment_location.location doc when RDoc::Markup::Document then return comment_location else raise ArgumentError, "unknown comment class #{comment_location.class}" end end ## # Path to this class or module for use with HTML generator output. def path http_url @store.rdoc.generator.class_dir end ## # Name to use to generate the url: # modules and classes that are aliases for another # module or class return the name of the latter. def name_for_path is_alias_for ? is_alias_for.full_name : full_name end ## # Returns the classes and modules that are not constants # aliasing another class or module. For use by formatters # only (caches its result). def non_aliases @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for } end ## # Updates the child modules or classes of class/module +parent+ by # deleting the ones that have been removed from the documentation. # # +parent_hash+ is either parent.modules_hash or # parent.classes_hash and +all_hash+ is ::all_modules_hash or # ::all_classes_hash. def remove_nodoc_children prefix = self.full_name + '::' modules_hash.each_key do |name| full_name = prefix + name modules_hash.delete name unless @store.modules_hash[full_name] end classes_hash.each_key do |name| full_name = prefix + name classes_hash.delete name unless @store.classes_hash[full_name] end end def remove_things my_things, other_files # :nodoc: my_things.delete_if do |file, things| next false unless other_files.include? file things.each do |thing| yield false, thing end true end end ## # Search record used by RDoc::Generator::JsonIndex def search_record [ name, full_name, full_name, '', path, '', snippet(@comment_location), ] end ## # Sets the store for this class or module and its contained code objects. def store= store super @attributes .each do |attr| attr.store = store end @constants .each do |const| const.store = store end @includes .each do |incl| incl.store = store end @extends .each do |ext| ext.store = store end @method_list.each do |meth| meth.store = store end end ## # Get the superclass of this class. Attempts to retrieve the superclass # object, returns the name if it is not known. def superclass @store.find_class_named(@superclass) || @superclass end ## # Set the superclass of this class to +superclass+ def superclass=(superclass) raise NoMethodError, "#{full_name} is a module" if module? @superclass = superclass end def to_s # :nodoc: if is_alias_for then "#{self.class.name} #{self.full_name} -> #{is_alias_for}" else super end end ## # 'module' or 'class' def type module? ? 'module' : 'class' end ## # Updates the child modules & classes by replacing the ones that are # aliases through a constant. # # The aliased module/class is replaced in the children and in # RDoc::Store#modules_hash or RDoc::Store#classes_hash # by a copy that has RDoc::ClassModule#is_alias_for set to # the aliased module/class, and this copy is added to #aliases # of the aliased module/class. # # Formatters can use the #non_aliases method to retrieve children that # are not aliases, for instance to list the namespace content, since # the aliased modules are included in the constants of the class/module, # that are listed separately. def update_aliases constants.each do |const| next unless cm = const.is_alias_for cm_alias = cm.dup cm_alias.name = const.name # Don't move top-level aliases under Object, they look ugly there unless RDoc::TopLevel === cm_alias.parent then cm_alias.parent = self cm_alias.full_name = nil # force update for new parent end cm_alias.aliases.clear cm_alias.is_alias_for = cm if cm.module? then @store.modules_hash[cm_alias.full_name] = cm_alias modules_hash[const.name] = cm_alias else @store.classes_hash[cm_alias.full_name] = cm_alias classes_hash[const.name] = cm_alias end cm.aliases << cm_alias end end ## # Deletes from #includes those whose module has been removed from the # documentation. #-- # FIXME: includes are not reliably removed, see _possible_bug test case def update_includes includes.reject! do |include| mod = include.module !(String === mod) && @store.modules_hash[mod.full_name].nil? end includes.uniq! end ## # Deletes from #extends those whose module has been removed from the # documentation. #-- # FIXME: like update_includes, extends are not reliably removed def update_extends extends.reject! do |ext| mod = ext.module !(String === mod) && @store.modules_hash[mod.full_name].nil? end extends.uniq! end end rdoc/token_stream.rb000064400000004734147635155430010540 0ustar00## # A TokenStream is a list of tokens, gathered during the parse of some entity # (say a method). Entities populate these streams by being registered with the # lexer. Any class can collect tokens by including TokenStream. From the # outside, you use such an object by calling the start_collecting_tokens # method, followed by calls to add_token and pop_token. module RDoc::TokenStream ## # Converts +token_stream+ to HTML wrapping various tokens with # elements. The following tokens types are wrapped in spans # with the given class names: # # TkCONSTANT :: 'ruby-constant' # TkKW :: 'ruby-keyword' # TkIVAR :: 'ruby-ivar' # TkOp :: 'ruby-operator' # TkId :: 'ruby-identifier' # TkNode :: 'ruby-node' # TkCOMMENT :: 'ruby-comment' # TkREGEXP :: 'ruby-regexp' # TkSTRING :: 'ruby-string' # TkVal :: 'ruby-value' # # Other token types are not wrapped in spans. def self.to_html token_stream token_stream.map do |t| next unless t style = case t when RDoc::RubyToken::TkCONSTANT then 'ruby-constant' when RDoc::RubyToken::TkKW then 'ruby-keyword' when RDoc::RubyToken::TkIVAR then 'ruby-ivar' when RDoc::RubyToken::TkOp then 'ruby-operator' when RDoc::RubyToken::TkId then 'ruby-identifier' when RDoc::RubyToken::TkNode then 'ruby-node' when RDoc::RubyToken::TkCOMMENT then 'ruby-comment' when RDoc::RubyToken::TkREGEXP then 'ruby-regexp' when RDoc::RubyToken::TkSTRING then 'ruby-string' when RDoc::RubyToken::TkVal then 'ruby-value' end text = CGI.escapeHTML t.text if style then "#{text}" else text end end.join end ## # Adds +tokens+ to the collected tokens def add_tokens(*tokens) tokens.flatten.each { |token| @token_stream << token } end alias add_token add_tokens ## # Starts collecting tokens def collect_tokens @token_stream = [] end alias start_collecting_tokens collect_tokens ## # Remove the last token from the collected tokens def pop_token @token_stream.pop end ## # Current token stream def token_stream @token_stream end ## # Returns a string representation of the token stream def tokens_to_s token_stream.map { |token| token.text }.join '' end end rdoc/stats/verbose.rb000064400000001726147635155430010646 0ustar00## # Stats printer that prints everything documented, including the documented # status class RDoc::Stats::Verbose < RDoc::Stats::Normal ## # Returns a marker for RDoc::CodeObject +co+ being undocumented def nodoc co " (undocumented)" unless co.documented? end def print_alias as # :nodoc: puts " alias #{as.new_name} #{as.old_name}#{nodoc as}" end def print_attribute attribute # :nodoc: puts " #{attribute.definition} #{attribute.name}#{nodoc attribute}" end def print_class(klass) # :nodoc: puts " class #{klass.full_name}#{nodoc klass}" end def print_constant(constant) # :nodoc: puts " #{constant.name}#{nodoc constant}" end def print_file(files_so_far, file) # :nodoc: super puts end def print_method(method) # :nodoc: puts " #{method.singleton ? '::' : '#'}#{method.name}#{nodoc method}" end def print_module(mod) # :nodoc: puts " module #{mod.full_name}#{nodoc mod}" end end rdoc/stats/quiet.rb000064400000001442147635155430010323 0ustar00## # Stats printer that prints nothing class RDoc::Stats::Quiet ## # Creates a new Quiet that will print nothing def initialize num_files @num_files = num_files end ## # Prints a message at the beginning of parsing def begin_adding(*) end ## # Prints when an alias is added def print_alias(*) end ## # Prints when an attribute is added def print_attribute(*) end ## # Prints when a class is added def print_class(*) end ## # Prints when a constant is added def print_constant(*) end ## # Prints when a file is added def print_file(*) end ## # Prints when a method is added def print_method(*) end ## # Prints when a module is added def print_module(*) end ## # Prints when RDoc is done def done_adding(*) end end rdoc/stats/normal.rb000064400000002437147635155430010471 0ustar00## # Stats printer that prints just the files being documented with a progress # bar class RDoc::Stats::Normal < RDoc::Stats::Quiet def begin_adding # :nodoc: puts "Parsing sources..." if $stdout.tty? end ## # Prints a file with a progress bar def print_file files_so_far, filename return unless $stdout.tty? progress_bar = sprintf("%3d%% [%2d/%2d] ", 100 * files_so_far / @num_files, files_so_far, @num_files) # Print a progress bar, but make sure it fits on a single line. Filename # will be truncated if necessary. terminal_width = (ENV['COLUMNS'] || 80).to_i max_filename_size = terminal_width - progress_bar.size if filename.size > max_filename_size then # Turn "some_long_filename.rb" to "...ong_filename.rb" filename = filename[(filename.size - max_filename_size) .. -1] filename[0..2] = "..." end # Pad the line with whitespaces so that leftover output from the # previous line doesn't show up. line = "#{progress_bar}#{filename}" padding = terminal_width - line.size line << (" " * padding) if padding > 0 $stdout.print("#{line}\r") $stdout.flush end def done_adding # :nodoc: puts if $stdout.tty? end end rdoc/normal_module.rb000064400000002555147635155430010701 0ustar00## # A normal module, like NormalClass class RDoc::NormalModule < RDoc::ClassModule def inspect # :nodoc: "#<%s:0x%x module %s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [ self.class, object_id, full_name, @includes, @extends, @attributes, @method_list, @aliases ] end ## # The definition of this module, module MyModuleName def definition "module #{full_name}" end ## # This is a module, returns true def module? true end def pretty_print q # :nodoc: q.group 2, "[module #{full_name}: ", "]" do q.breakable q.text "includes:" q.breakable q.seplist @includes do |inc| q.pp inc end q.breakable q.breakable q.text "constants:" q.breakable q.seplist @constants do |const| q.pp const end q.text "attributes:" q.breakable q.seplist @attributes do |attr| q.pp attr end q.breakable q.text "methods:" q.breakable q.seplist @method_list do |meth| q.pp meth end q.breakable q.text "aliases:" q.breakable q.seplist @aliases do |aliaz| q.pp aliaz end q.breakable q.text "comment:" q.breakable q.pp comment end end ## # Modules don't have one, raises NoMethodError def superclass raise NoMethodError, "#{full_name} is a module" end end rdoc/rubygems_hook.rb000064400000011646147635155430010722 0ustar00require 'rubygems' require 'rubygems/user_interaction' require 'fileutils' require 'rdoc' ## # Gem::RDoc provides methods to generate RDoc and ri data for installed gems # upon gem installation. # # This file is automatically required by RubyGems 1.9 and newer. class RDoc::RubygemsHook include Gem::UserInteraction @rdoc_version = nil @specs = [] ## # Force installation of documentation? attr_accessor :force ## # Generate rdoc? attr_accessor :generate_rdoc ## # Generate ri data? attr_accessor :generate_ri class << self ## # Loaded version of RDoc. Set by ::load_rdoc attr_reader :rdoc_version end ## # Post installs hook that generates documentation for each specification in # +specs+ def self.generation_hook installer, specs types = installer.document generate_rdoc = types.include? 'rdoc' generate_ri = types.include? 'ri' specs.each do |spec| new(spec, generate_rdoc, generate_ri).generate end end ## # Loads the RDoc generator def self.load_rdoc return if @rdoc_version require 'rdoc/rdoc' @rdoc_version = Gem::Version.new ::RDoc::VERSION end ## # Creates a new documentation generator for +spec+. RDoc and ri data # generation can be enabled or disabled through +generate_rdoc+ and # +generate_ri+ respectively. # # Only +generate_ri+ is enabled by default. def initialize spec, generate_rdoc = false, generate_ri = true @doc_dir = spec.doc_dir @force = false @rdoc = nil @spec = spec @generate_rdoc = generate_rdoc @generate_ri = generate_ri @rdoc_dir = spec.doc_dir 'rdoc' @ri_dir = spec.doc_dir 'ri' end ## # Removes legacy rdoc arguments from +args+ #-- # TODO move to RDoc::Options def delete_legacy_args args args.delete '--inline-source' args.delete '--promiscuous' args.delete '-p' args.delete '--one-file' end ## # Generates documentation using the named +generator+ ("darkfish" or "ri") # and following the given +options+. # # Documentation will be generated into +destination+ def document generator, options, destination generator_name = generator options = options.dup options.exclude ||= [] # TODO maybe move to RDoc::Options#finish options.setup_generator generator options.op_dir = destination options.finish generator = options.generator.new @rdoc.store, options @rdoc.options = options @rdoc.generator = generator say "Installing #{generator_name} documentation for #{@spec.full_name}" FileUtils.mkdir_p options.op_dir Dir.chdir options.op_dir do begin @rdoc.class.current = @rdoc @rdoc.generator.generate ensure @rdoc.class.current = nil end end end ## # Generates RDoc and ri data def generate return if @spec.default_gem? return unless @generate_ri or @generate_rdoc setup options = nil args = @spec.rdoc_options args.concat @spec.require_paths args.concat @spec.extra_rdoc_files case config_args = Gem.configuration[:rdoc] when String then args = args.concat config_args.split when Array then args = args.concat config_args end delete_legacy_args args Dir.chdir @spec.full_gem_path do options = ::RDoc::Options.new options.default_title = "#{@spec.full_name} Documentation" options.parse args end options.quiet = !Gem.configuration.really_verbose @rdoc = new_rdoc @rdoc.options = options store = RDoc::Store.new store.encoding = options.encoding if options.respond_to? :encoding store.dry_run = options.dry_run store.main = options.main_page store.title = options.title @rdoc.store = store say "Parsing documentation for #{@spec.full_name}" Dir.chdir @spec.full_gem_path do @rdoc.parse_files options.files end document 'ri', options, @ri_dir if @generate_ri and (@force or not File.exist? @ri_dir) document 'darkfish', options, @rdoc_dir if @generate_rdoc and (@force or not File.exist? @rdoc_dir) end ## # #new_rdoc creates a new RDoc instance. This method is provided only to # make testing easier. def new_rdoc # :nodoc: ::RDoc::RDoc.new end ## # Is rdoc documentation installed? def rdoc_installed? File.exist? @rdoc_dir end ## # Removes generated RDoc and ri data def remove base_dir = @spec.base_dir raise Gem::FilePermissionError, base_dir unless File.writable? base_dir FileUtils.rm_rf @rdoc_dir FileUtils.rm_rf @ri_dir end ## # Is ri data installed? def ri_installed? File.exist? @ri_dir end ## # Prepares the spec for documentation generation def setup self.class.load_rdoc raise Gem::FilePermissionError, @doc_dir if File.exist?(@doc_dir) and not File.writable?(@doc_dir) FileUtils.mkdir_p @doc_dir unless File.exist? @doc_dir end end rdoc/store.rb000064400000054506147635155430007203 0ustar00require 'fileutils' ## # A set of rdoc data for a single project (gem, path, etc.). # # The store manages reading and writing ri data for a project and maintains a # cache of methods, classes and ancestors in the store. # # The store maintains a #cache of its contents for faster lookup. After # adding items to the store it must be flushed using #save_cache. The cache # contains the following structures: # # @cache = { # :ancestors => {}, # class name => ancestor names # :attributes => {}, # class name => attributes # :class_methods => {}, # class name => class methods # :instance_methods => {}, # class name => instance methods # :modules => [], # classes and modules in this store # :pages => [], # page names # } #-- # TODO need to prune classes class RDoc::Store ## # Errors raised from loading or saving the store class Error < RDoc::Error end ## # Raised when a stored file for a class, module, page or method is missing. class MissingFileError < Error ## # The store the file should exist in attr_reader :store ## # The file the #name should be saved as attr_reader :file ## # The name of the object the #file would be loaded from attr_reader :name ## # Creates a new MissingFileError for the missing +file+ for the given # +name+ that should have been in the +store+. def initialize store, file, name @store = store @file = file @name = name end def message # :nodoc: "store at #{@store.path} missing file #{@file} for #{@name}" end end ## # Stores the name of the C variable a class belongs to. This helps wire up # classes defined from C across files. attr_reader :c_enclosure_classes # :nodoc: attr_reader :c_enclosure_names # :nodoc: ## # Maps C variables to class or module names for each parsed C file. attr_reader :c_class_variables ## # Maps C variables to singleton class names for each parsed C file. attr_reader :c_singleton_class_variables ## # If true this Store will not write any files attr_accessor :dry_run ## # Path this store reads or writes attr_accessor :path ## # The RDoc::RDoc driver for this parse tree. This allows classes consulting # the documentation tree to access user-set options, for example. attr_accessor :rdoc ## # Type of ri datastore this was loaded from. See RDoc::RI::Driver, # RDoc::RI::Paths. attr_accessor :type ## # The contents of the Store attr_reader :cache ## # The encoding of the contents in the Store attr_accessor :encoding ## # Creates a new Store of +type+ that will load or save to +path+ def initialize path = nil, type = nil @dry_run = false @encoding = nil @path = path @rdoc = nil @type = type @cache = { :ancestors => {}, :attributes => {}, :class_methods => {}, :c_class_variables => {}, :c_singleton_class_variables => {}, :encoding => @encoding, :instance_methods => {}, :main => nil, :modules => [], :pages => [], :title => nil, } @classes_hash = {} @modules_hash = {} @files_hash = {} @c_enclosure_classes = {} @c_enclosure_names = {} @c_class_variables = {} @c_singleton_class_variables = {} @unique_classes = nil @unique_modules = nil end ## # Adds +module+ as an enclosure (namespace) for the given +variable+ for C # files. def add_c_enclosure variable, namespace @c_enclosure_classes[variable] = namespace end ## # Adds C variables from an RDoc::Parser::C def add_c_variables c_parser filename = c_parser.top_level.relative_name @c_class_variables[filename] = make_variable_map c_parser.classes @c_singleton_class_variables[filename] = c_parser.singleton_classes end ## # Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the # created RDoc::TopLevel. def add_file absolute_name, relative_name = absolute_name unless top_level = @files_hash[relative_name] then top_level = RDoc::TopLevel.new absolute_name, relative_name top_level.store = self @files_hash[relative_name] = top_level end top_level end ## # Returns all classes discovered by RDoc def all_classes @classes_hash.values end ## # Returns all classes and modules discovered by RDoc def all_classes_and_modules @classes_hash.values + @modules_hash.values end ## # All TopLevels known to RDoc def all_files @files_hash.values end ## # Returns all modules discovered by RDoc def all_modules modules_hash.values end ## # Ancestors cache accessor. Maps a klass name to an Array of its ancestors # in this store. If Foo in this store inherits from Object, Kernel won't be # listed (it will be included from ruby's ri store). def ancestors @cache[:ancestors] end ## # Attributes cache accessor. Maps a class to an Array of its attributes. def attributes @cache[:attributes] end ## # Path to the cache file def cache_path File.join @path, 'cache.ri' end ## # Path to the ri data for +klass_name+ def class_file klass_name name = klass_name.split('::').last File.join class_path(klass_name), "cdesc-#{name}.ri" end ## # Class methods cache accessor. Maps a class to an Array of its class # methods (not full name). def class_methods @cache[:class_methods] end ## # Path where data for +klass_name+ will be stored (methods or class data) def class_path klass_name File.join @path, *klass_name.split('::') end ## # Hash of all classes known to RDoc def classes_hash @classes_hash end ## # Removes empty items and ensures item in each collection are unique and # sorted def clean_cache_collection collection # :nodoc: collection.each do |name, item| if item.empty? then collection.delete name else # HACK mongrel-1.1.5 documents its files twice item.uniq! item.sort! end end end ## # Prepares the RDoc code object tree for use by a generator. # # It finds unique classes/modules defined, and replaces classes/modules that # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for # set. # # It updates the RDoc::ClassModule#constant_aliases attribute of "real" # classes or modules. # # It also completely removes the classes and modules that should be removed # from the documentation and the methods that have a visibility below # +min_visibility+, which is the --visibility option. # # See also RDoc::Context#remove_from_documentation? def complete min_visibility fix_basic_object_inheritance # cache included modules before they are removed from the documentation all_classes_and_modules.each { |cm| cm.ancestors } remove_nodoc @classes_hash remove_nodoc @modules_hash @unique_classes = find_unique @classes_hash @unique_modules = find_unique @modules_hash unique_classes_and_modules.each do |cm| cm.complete min_visibility end @files_hash.each_key do |file_name| tl = @files_hash[file_name] unless tl.text? then tl.modules_hash.clear tl.classes_hash.clear tl.classes_or_modules.each do |cm| name = cm.full_name if cm.type == 'class' then tl.classes_hash[name] = cm if @classes_hash[name] else tl.modules_hash[name] = cm if @modules_hash[name] end end end end end ## # Hash of all files known to RDoc def files_hash @files_hash end ## # Finds the enclosure (namespace) for the given C +variable+. def find_c_enclosure variable @c_enclosure_classes.fetch variable do break unless name = @c_enclosure_names[variable] mod = find_class_or_module name unless mod then loaded_mod = load_class_data name file = loaded_mod.in_files.first return unless file # legacy data source file.store = self mod = file.add_module RDoc::NormalModule, name end @c_enclosure_classes[variable] = mod end end ## # Finds the class with +name+ in all discovered classes def find_class_named name @classes_hash[name] end ## # Finds the class with +name+ starting in namespace +from+ def find_class_named_from name, from from = find_class_named from unless RDoc::Context === from until RDoc::TopLevel === from do return nil unless from klass = from.find_class_named name return klass if klass from = from.parent end find_class_named name end ## # Finds the class or module with +name+ def find_class_or_module name name = $' if name =~ /^::/ @classes_hash[name] || @modules_hash[name] end ## # Finds the file with +name+ in all discovered files def find_file_named name @files_hash[name] end ## # Finds the module with +name+ in all discovered modules def find_module_named name @modules_hash[name] end ## # Returns the RDoc::TopLevel that is a text file and has the given # +file_name+ def find_text_page file_name @files_hash.each_value.find do |file| file.text? and file.full_name == file_name end end ## # Finds unique classes/modules defined in +all_hash+, # and returns them as an array. Performs the alias # updates in +all_hash+: see ::complete. #-- # TODO aliases should be registered by Context#add_module_alias def find_unique all_hash unique = [] all_hash.each_pair do |full_name, cm| unique << cm if full_name == cm.full_name end unique end ## # Fixes the erroneous BasicObject < Object in 1.9. # # Because we assumed all classes without a stated superclass # inherit from Object, we have the above wrong inheritance. # # We fix BasicObject right away if we are running in a Ruby # version >= 1.9. If not, we may be documenting 1.9 source # while running under 1.8: we search the files of BasicObject # for "object.c", and fix the inheritance if we find it. def fix_basic_object_inheritance basic = classes_hash['BasicObject'] return unless basic if RUBY_VERSION >= '1.9' basic.superclass = nil elsif basic.in_files.any? { |f| File.basename(f.full_name) == 'object.c' } basic.superclass = nil end end ## # Friendly rendition of #path def friendly_path case type when :gem then parent = File.expand_path '..', @path "gem #{File.basename parent}" when :home then '~/.rdoc' when :site then 'ruby site' when :system then 'ruby core' else @path end end def inspect # :nodoc: "#<%s:0x%x %s %p>" % [self.class, object_id, @path, module_names.sort] end ## # Instance methods cache accessor. Maps a class to an Array of its # instance methods (not full name). def instance_methods @cache[:instance_methods] end ## # Loads all items from this store into memory. This recreates a # documentation tree for use by a generator def load_all load_cache module_names.each do |module_name| mod = find_class_or_module(module_name) || load_class(module_name) # load method documentation since the loaded class/module does not have # it loaded_methods = mod.method_list.map do |method| load_method module_name, method.full_name end mod.method_list.replace loaded_methods loaded_attributes = mod.attributes.map do |attribute| load_method module_name, attribute.full_name end mod.attributes.replace loaded_attributes end all_classes_and_modules.each do |mod| descendent_re = /^#{mod.full_name}::[^:]+$/ module_names.each do |name| next unless name =~ descendent_re descendent = find_class_or_module name case descendent when RDoc::NormalClass then mod.classes_hash[name] = descendent when RDoc::NormalModule then mod.modules_hash[name] = descendent end end end @cache[:pages].each do |page_name| page = load_page page_name @files_hash[page_name] = page end end ## # Loads cache file for this store def load_cache #orig_enc = @encoding open cache_path, 'rb' do |io| @cache = Marshal.load io.read end load_enc = @cache[:encoding] # TODO this feature will be time-consuming to add: # a) Encodings may be incompatible but transcodeable # b) Need to warn in the appropriate spots, wherever they may be # c) Need to handle cross-cache differences in encodings # d) Need to warn when generating into a cache with different encodings # #if orig_enc and load_enc != orig_enc then # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \ # "from #{path}/cache.ri" unless # Encoding.compatible? orig_enc, load_enc #end @encoding = load_enc unless @encoding @cache[:pages] ||= [] @cache[:main] ||= nil @cache[:c_class_variables] ||= {} @cache[:c_singleton_class_variables] ||= {} @cache[:c_class_variables].each do |_, map| map.each do |variable, name| @c_enclosure_names[variable] = name end end @cache rescue Errno::ENOENT end ## # Loads ri data for +klass_name+ and hooks it up to this store. def load_class klass_name obj = load_class_data klass_name obj.store = self case obj when RDoc::NormalClass then @classes_hash[klass_name] = obj when RDoc::NormalModule then @modules_hash[klass_name] = obj end end ## # Loads ri data for +klass_name+ def load_class_data klass_name file = class_file klass_name open file, 'rb' do |io| Marshal.load io.read end rescue Errno::ENOENT => e error = MissingFileError.new(self, file, klass_name) error.set_backtrace e.backtrace raise error end ## # Loads ri data for +method_name+ in +klass_name+ def load_method klass_name, method_name file = method_file klass_name, method_name open file, 'rb' do |io| obj = Marshal.load io.read obj.store = self obj.parent = find_class_or_module(klass_name) || load_class(klass_name) unless obj.parent obj end rescue Errno::ENOENT => e error = MissingFileError.new(self, file, klass_name + method_name) error.set_backtrace e.backtrace raise error end ## # Loads ri data for +page_name+ def load_page page_name file = page_file page_name open file, 'rb' do |io| obj = Marshal.load io.read obj.store = self obj end rescue Errno::ENOENT => e error = MissingFileError.new(self, file, page_name) error.set_backtrace e.backtrace raise error end ## # Gets the main page for this RDoc store. This page is used as the root of # the RDoc server. def main @cache[:main] end ## # Sets the main page for this RDoc store. def main= page @cache[:main] = page end ## # Converts the variable => ClassModule map +variables+ from a C parser into # a variable => class name map. def make_variable_map variables map = {} variables.each { |variable, class_module| map[variable] = class_module.full_name } map end ## # Path to the ri data for +method_name+ in +klass_name+ def method_file klass_name, method_name method_name = method_name.split('::').last method_name =~ /#(.*)/ method_type = $1 ? 'i' : 'c' method_name = $1 if $1 method_name = if ''.respond_to? :ord then method_name.gsub(/\W/) { "%%%02x" % $&[0].ord } else method_name.gsub(/\W/) { "%%%02x" % $&[0] } end File.join class_path(klass_name), "#{method_name}-#{method_type}.ri" end ## # Modules cache accessor. An Array of all the module (and class) names in # the store. def module_names @cache[:modules] end ## # Hash of all modules known to RDoc def modules_hash @modules_hash end ## # Returns the RDoc::TopLevel that is a text file and has the given +name+ def page name @files_hash.each_value.find do |file| file.text? and file.page_name == name end end ## # Path to the ri data for +page_name+ def page_file page_name file_name = File.basename(page_name).gsub('.', '_') File.join @path, File.dirname(page_name), "page-#{file_name}.ri" end ## # Removes from +all_hash+ the contexts that are nodoc or have no content. # # See RDoc::Context#remove_from_documentation? def remove_nodoc all_hash all_hash.keys.each do |name| context = all_hash[name] all_hash.delete(name) if context.remove_from_documentation? end end ## # Saves all entries in the store def save load_cache all_classes_and_modules.each do |klass| save_class klass klass.each_method do |method| save_method klass, method end klass.each_attribute do |attribute| save_method klass, attribute end end all_files.each do |file| save_page file end save_cache end ## # Writes the cache file for this store def save_cache clean_cache_collection @cache[:ancestors] clean_cache_collection @cache[:attributes] clean_cache_collection @cache[:class_methods] clean_cache_collection @cache[:instance_methods] @cache[:modules].uniq! @cache[:modules].sort! @cache[:pages].uniq! @cache[:pages].sort! @cache[:encoding] = @encoding # this gets set twice due to assert_cache @cache[:c_class_variables].merge! @c_class_variables @cache[:c_singleton_class_variables].merge! @c_singleton_class_variables return if @dry_run marshal = Marshal.dump @cache open cache_path, 'wb' do |io| io.write marshal end end ## # Writes the ri data for +klass+ (or module) def save_class klass full_name = klass.full_name FileUtils.mkdir_p class_path(full_name) unless @dry_run @cache[:modules] << full_name path = class_file full_name begin disk_klass = load_class full_name klass = disk_klass.merge klass rescue MissingFileError end # BasicObject has no ancestors ancestors = klass.direct_ancestors.compact.map do |ancestor| # HACK for classes we don't know about (class X < RuntimeError) String === ancestor ? ancestor : ancestor.full_name end @cache[:ancestors][full_name] ||= [] @cache[:ancestors][full_name].concat ancestors attribute_definitions = klass.attributes.map do |attribute| "#{attribute.definition} #{attribute.name}" end unless attribute_definitions.empty? then @cache[:attributes][full_name] ||= [] @cache[:attributes][full_name].concat attribute_definitions end to_delete = [] unless klass.method_list.empty? then @cache[:class_methods][full_name] ||= [] @cache[:instance_methods][full_name] ||= [] class_methods, instance_methods = klass.method_list.partition { |meth| meth.singleton } class_methods = class_methods. map { |method| method.name } instance_methods = instance_methods.map { |method| method.name } attribute_names = klass.attributes.map { |attr| attr.name } old = @cache[:class_methods][full_name] - class_methods to_delete.concat old.map { |method| method_file full_name, "#{full_name}::#{method}" } old = @cache[:instance_methods][full_name] - instance_methods - attribute_names to_delete.concat old.map { |method| method_file full_name, "#{full_name}##{method}" } @cache[:class_methods][full_name] = class_methods @cache[:instance_methods][full_name] = instance_methods end return if @dry_run FileUtils.rm_f to_delete marshal = Marshal.dump klass open path, 'wb' do |io| io.write marshal end end ## # Writes the ri data for +method+ on +klass+ def save_method klass, method full_name = klass.full_name FileUtils.mkdir_p class_path(full_name) unless @dry_run cache = if method.singleton then @cache[:class_methods] else @cache[:instance_methods] end cache[full_name] ||= [] cache[full_name] << method.name return if @dry_run marshal = Marshal.dump method open method_file(full_name, method.full_name), 'wb' do |io| io.write marshal end end ## # Writes the ri data for +page+ def save_page page return unless page.text? path = page_file page.full_name FileUtils.mkdir_p File.dirname(path) unless @dry_run cache[:pages] ||= [] cache[:pages] << page.full_name return if @dry_run marshal = Marshal.dump page open path, 'wb' do |io| io.write marshal end end ## # Source of the contents of this store. # # For a store from a gem the source is the gem name. For a store from the # home directory the source is "home". For system ri store (the standard # library documentation) the source is"ruby". For a store from the site # ri directory the store is "site". For other stores the source is the # #path. def source case type when :gem then File.basename File.expand_path '..', @path when :home then 'home' when :site then 'site' when :system then 'ruby' else @path end end ## # Gets the title for this RDoc store. This is used as the title in each # page on the RDoc server def title @cache[:title] end ## # Sets the title page for this RDoc store. def title= title @cache[:title] = title end ## # Returns the unique classes discovered by RDoc. # # ::complete must have been called prior to using this method. def unique_classes @unique_classes end ## # Returns the unique classes and modules discovered by RDoc. # ::complete must have been called prior to using this method. def unique_classes_and_modules @unique_classes + @unique_modules end ## # Returns the unique modules discovered by RDoc. # ::complete must have been called prior to using this method. def unique_modules @unique_modules end end rdoc/code_object.rb000064400000017331147635155430010302 0ustar00## # Base class for the RDoc code tree. # # We contain the common stuff for contexts (which are containers) and other # elements (methods, attributes and so on) # # Here's the tree of the CodeObject subclasses: # # * RDoc::Context # * RDoc::TopLevel # * RDoc::ClassModule # * RDoc::AnonClass (never used so far) # * RDoc::NormalClass # * RDoc::NormalModule # * RDoc::SingleClass # * RDoc::MethodAttr # * RDoc::Attr # * RDoc::AnyMethod # * RDoc::GhostMethod # * RDoc::MetaMethod # * RDoc::Alias # * RDoc::Constant # * RDoc::Require # * RDoc::Include class RDoc::CodeObject include RDoc::Text ## # Our comment attr_reader :comment ## # Do we document our children? attr_reader :document_children ## # Do we document ourselves? attr_reader :document_self ## # Are we done documenting (ie, did we come across a :enddoc:)? attr_reader :done_documenting ## # Which file this code object was defined in attr_reader :file ## # Force documentation of this CodeObject attr_reader :force_documentation ## # Line in #file where this CodeObject was defined attr_accessor :line ## # Hash of arbitrary metadata for this CodeObject attr_reader :metadata ## # Offset in #file where this CodeObject was defined #-- # TODO character or byte? attr_accessor :offset ## # Sets the parent CodeObject attr_writer :parent ## # Did we ever receive a +:nodoc:+ directive? attr_reader :received_nodoc ## # Set the section this CodeObject is in attr_writer :section ## # The RDoc::Store for this object. attr_accessor :store ## # We are the model of the code, but we know that at some point we will be # worked on by viewers. By implementing the Viewable protocol, viewers can # associated themselves with these objects. attr_accessor :viewer ## # Creates a new CodeObject that will document itself and its children def initialize @metadata = {} @comment = '' @parent = nil @parent_name = nil # for loading @parent_class = nil # for loading @section = nil @section_title = nil # for loading @file = nil @full_name = nil @store = nil initialize_visibility end ## # Initializes state for visibility of this CodeObject and its children. def initialize_visibility # :nodoc: @document_children = true @document_self = true @done_documenting = false @force_documentation = false @received_nodoc = false @ignored = false end ## # Replaces our comment with +comment+, unless it is empty. def comment=(comment) @comment = case comment when NilClass then '' when RDoc::Markup::Document then comment when RDoc::Comment then comment.normalize else if comment and not comment.empty? then normalize_comment comment else # HACK correct fix is to have #initialize create @comment # with the correct encoding if String === @comment and Object.const_defined? :Encoding and @comment.empty? then @comment.force_encoding comment.encoding end @comment end end end ## # Should this CodeObject be shown in documentation? def display? @document_self and not @ignored end ## # Enables or disables documentation of this CodeObject's children unless it # has been turned off by :enddoc: def document_children=(document_children) @document_children = document_children unless @done_documenting end ## # Enables or disables documentation of this CodeObject unless it has been # turned off by :enddoc:. If the argument is +nil+ it means the # documentation is turned off by +:nodoc:+. def document_self=(document_self) return if @done_documenting @document_self = document_self @received_nodoc = true if document_self.nil? end ## # Does this object have a comment with content or is #received_nodoc true? def documented? @received_nodoc or !@comment.empty? end ## # Turns documentation on/off, and turns on/off #document_self # and #document_children. # # Once documentation has been turned off (by +:enddoc:+), # the object will refuse to turn #document_self or # #document_children on, so +:doc:+ and +:start_doc:+ directives # will have no effect in the current file. def done_documenting=(value) @done_documenting = value @document_self = !value @document_children = @document_self end ## # Yields each parent of this CodeObject. See also # RDoc::ClassModule#each_ancestor def each_parent code_object = self while code_object = code_object.parent do yield code_object end self end ## # File name where this CodeObject was found. # # See also RDoc::Context#in_files def file_name return unless @file @file.absolute_name end ## # Force the documentation of this object unless documentation # has been turned off by :enddoc: #-- # HACK untested, was assigning to an ivar def force_documentation=(value) @force_documentation = value unless @done_documenting end ## # Sets the full_name overriding any computed full name. # # Set to +nil+ to clear RDoc's cached value def full_name= full_name @full_name = full_name end ## # Use this to ignore a CodeObject and all its children until found again # (#record_location is called). An ignored item will not be shown in # documentation. # # See github issue #55 # # The ignored status is temporary in order to allow implementation details # to be hidden. At the end of processing a file RDoc allows all classes # and modules to add new documentation to previously created classes. # # If a class was ignored (via stopdoc) then reopened later with additional # documentation it should be shown. If a class was ignored and never # reopened it should not be shown. The ignore flag allows this to occur. def ignore @ignored = true stop_doc end ## # Has this class been ignored? def ignored? @ignored end ## # Our parent CodeObject. The parent may be missing for classes loaded from # legacy RI data stores. def parent return @parent if @parent return nil unless @parent_name if @parent_class == RDoc::TopLevel then @parent = @store.add_file @parent_name else @parent = @store.find_class_or_module @parent_name return @parent if @parent begin @parent = @store.load_class @parent_name rescue RDoc::Store::MissingFileError nil end end end ## # File name of our parent def parent_file_name @parent ? @parent.base_name : '(unknown)' end ## # Name of our parent def parent_name @parent ? @parent.full_name : '(unknown)' end ## # Records the RDoc::TopLevel (file) where this code object was defined def record_location top_level @ignored = false @file = top_level end ## # The section this CodeObject is in. Sections allow grouping of constants, # attributes and methods inside a class or module. def section return @section if @section @section = parent.add_section @section_title if parent end ## # Enable capture of documentation unless documentation has been # turned off by :enddoc: def start_doc return if @done_documenting @document_self = true @document_children = true @ignored = false end ## # Disable capture of documentation def stop_doc @document_self = false @document_children = false end end rdoc/context/section.rb000064400000011471147635155430011171 0ustar00## # A section of documentation like: # # # :section: The title # # The body # # Sections can be referenced multiple times and will be collapsed into a # single section. class RDoc::Context::Section include RDoc::Text MARSHAL_VERSION = 0 # :nodoc: ## # Section comment attr_reader :comment ## # Section comments attr_reader :comments ## # Context this Section lives in attr_reader :parent ## # Section title attr_reader :title @@sequence = "SEC00000" ## # Creates a new section with +title+ and +comment+ def initialize parent, title, comment @parent = parent @title = title ? title.strip : title @@sequence.succ! @sequence = @@sequence.dup @comments = [] add_comment comment end ## # Sections are equal when they have the same #title def == other self.class === other and @title == other.title end ## # Adds +comment+ to this section def add_comment comment comment = extract_comment comment return if comment.empty? case comment when RDoc::Comment then @comments << comment when RDoc::Markup::Document then @comments.concat comment.parts when Array then @comments.concat comment else raise TypeError, "unknown comment type: #{comment.inspect}" end end ## # Anchor reference for linking to this section def aref title = @title || '[untitled]' CGI.escape(title).gsub('%', '-').sub(/^-/, '') end ## # Extracts the comment for this section from the original comment block. # If the first line contains :section:, strip it and use the rest. # Otherwise remove lines up to the line containing :section:, and look # for those lines again at the end and remove them. This lets us write # # # :section: The title # # The body def extract_comment comment case comment when Array then comment.map do |c| extract_comment c end when nil RDoc::Comment.new '' when RDoc::Comment then if comment.text =~ /^#[ \t]*:section:.*\n/ then start = $` rest = $' comment.text = if start.empty? then rest else rest.sub(/#{start.chomp}\Z/, '') end end comment when RDoc::Markup::Document then comment else raise TypeError, "unknown comment #{comment.inspect}" end end def inspect # :nodoc: "#<%s:0x%x %p>" % [self.class, object_id, title] end ## # The files comments in this section come from def in_files return [] if @comments.empty? case @comments when Array then @comments.map do |comment| comment.file end when RDoc::Markup::Document then @comment.parts.map do |document| document.file end else raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" end end ## # Serializes this Section. The title and parsed comment are saved, but not # the section parent which must be restored manually. def marshal_dump [ MARSHAL_VERSION, @title, parse, ] end ## # De-serializes this Section. The section parent must be restored manually. def marshal_load array @parent = nil @title = array[1] @comments = array[2] end ## # Parses +comment_location+ into an RDoc::Markup::Document composed of # multiple RDoc::Markup::Documents with their file set. def parse case @comments when String then super when Array then docs = @comments.map do |comment, location| doc = super comment doc.file = location if location doc end RDoc::Markup::Document.new(*docs) when RDoc::Comment then doc = super @comments.text, comments.format doc.file = @comments.location doc when RDoc::Markup::Document then return @comments else raise ArgumentError, "unknown comment class #{comments.class}" end end ## # The section's title, or 'Top Section' if the title is nil. # # This is used by the table of contents template so the name is silly. def plain_html @title || 'Top Section' end ## # Removes a comment from this section if it is from the same file as # +comment+ def remove_comment comment return if @comments.empty? case @comments when Array then @comments.delete_if do |my_comment| my_comment.file == comment.file end when RDoc::Markup::Document then @comments.parts.delete_if do |document| document.file == comment.file.name end else raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" end end ## # Section sequence number (deprecated) def sequence warn "RDoc::Context::Section#sequence is deprecated, use #aref" @sequence end end rdoc/options.rb000064400000070764147635155430007546 0ustar00require 'optparse' require 'pathname' ## # RDoc::Options handles the parsing and storage of options # # == Saved Options # # You can save some options like the markup format in the # .rdoc_options file in your gem. The easiest way to do this is: # # rdoc --markup tomdoc --write-options # # Which will automatically create the file and fill it with the options you # specified. # # The following options will not be saved since they interfere with the user's # preferences or with the normal operation of RDoc: # # * +--coverage-report+ # * +--dry-run+ # * +--encoding+ # * +--force-update+ # * +--format+ # * +--pipe+ # * +--quiet+ # * +--template+ # * +--verbose+ # # == Custom Options # # Generators can hook into RDoc::Options to add generator-specific command # line options. # # When --format is encountered in ARGV, RDoc calls ::setup_options on # the generator class to add extra options to the option parser. Options for # custom generators must occur after --format. rdoc --help # will list options for all installed generators. # # Example: # # class RDoc::Generator::Spellcheck # RDoc::RDoc.add_generator self # # def self.setup_options rdoc_options # op = rdoc_options.option_parser # # op.on('--spell-dictionary DICTIONARY', # RDoc::Options::Path) do |dictionary| # rdoc_options.spell_dictionary = dictionary # end # end # end # # == Option Validators # # OptionParser validators will validate and cast user input values. In # addition to the validators that ship with OptionParser (String, Integer, # Float, TrueClass, FalseClass, Array, Regexp, Date, Time, URI, etc.), # RDoc::Options adds Path, PathArray and Template. class RDoc::Options ## # The deprecated options. DEPRECATED = { '--accessor' => 'support discontinued', '--diagram' => 'support discontinued', '--help-output' => 'support discontinued', '--image-format' => 'was an option for --diagram', '--inline-source' => 'source code is now always inlined', '--merge' => 'ri now always merges class information', '--one-file' => 'support discontinued', '--op-name' => 'support discontinued', '--opname' => 'support discontinued', '--promiscuous' => 'files always only document their content', '--ri-system' => 'Ruby installers use other techniques', } ## # RDoc options ignored (or handled specially) by --write-options SPECIAL = %w[ coverage_report dry_run encoding files force_output force_update generator generator_name generator_options generators op_dir option_parser pipe rdoc_include root static_path stylesheet_url template template_dir update_output_dir verbosity write_options ] ## # Option validator for OptionParser that matches a directory that exists on # the filesystem. Directory = Object.new ## # Option validator for OptionParser that matches a file or directory that # exists on the filesystem. Path = Object.new ## # Option validator for OptionParser that matches a comma-separated list of # files or directories that exist on the filesystem. PathArray = Object.new ## # Option validator for OptionParser that matches a template directory for an # installed generator that lives in # "rdoc/generator/template/#{template_name}" Template = Object.new ## # Character-set for HTML output. #encoding is preferred over #charset attr_accessor :charset ## # If true, RDoc will not write any files. attr_accessor :dry_run ## # The output encoding. All input files will be transcoded to this encoding. # # The default encoding is UTF-8. This is set via --encoding. attr_accessor :encoding ## # Files matching this pattern will be excluded attr_accessor :exclude ## # The list of files to be processed attr_accessor :files ## # Create the output even if the output directory does not look # like an rdoc output directory attr_accessor :force_output ## # Scan newer sources than the flag file if true. attr_accessor :force_update ## # Formatter to mark up text with attr_accessor :formatter ## # Description of the output generator (set with the --format option) attr_accessor :generator ## # For #== attr_reader :generator_name # :nodoc: ## # Loaded generator options. Used to prevent --help from loading the same # options multiple times. attr_accessor :generator_options ## # Old rdoc behavior: hyperlink all words that match a method name, # even if not preceded by '#' or '::' attr_accessor :hyperlink_all ## # Include line numbers in the source code attr_accessor :line_numbers ## # Name of the file, class or module to display in the initial index page (if # not specified the first file we encounter is used) attr_accessor :main_page ## # The default markup format. The default is 'rdoc'. 'markdown', 'tomdoc' # and 'rd' are also built-in. attr_accessor :markup ## # If true, only report on undocumented files attr_accessor :coverage_report ## # The name of the output directory attr_accessor :op_dir ## # The OptionParser for this instance attr_accessor :option_parser ## # Directory where guides, FAQ, and other pages not associated with a class # live. You may leave this unset if these are at the root of your project. attr_accessor :page_dir ## # Is RDoc in pipe mode? attr_accessor :pipe ## # Array of directories to search for files to satisfy an :include: attr_accessor :rdoc_include ## # Root of the source documentation will be generated for. Set this when # building documentation outside the source directory. Defaults to the # current directory. attr_accessor :root ## # Include the '#' at the front of hyperlinked instance method names attr_accessor :show_hash ## # Directory to copy static files from attr_accessor :static_path ## # The number of columns in a tab attr_accessor :tab_width ## # Template to be used when generating output attr_accessor :template ## # Directory the template lives in attr_accessor :template_dir ## # Documentation title attr_accessor :title ## # Should RDoc update the timestamps in the output dir? attr_accessor :update_output_dir ## # Verbosity, zero means quiet attr_accessor :verbosity ## # URL of web cvs frontend attr_accessor :webcvs ## # Minimum visibility of a documented method. One of +:public+, # +:protected+, +:private+. May be overridden on a per-method # basis with the :doc: directive. attr_accessor :visibility def initialize # :nodoc: init_ivars end def init_ivars # :nodoc: @dry_run = false @exclude = [] @files = nil @force_output = false @force_update = true @generator = nil @generator_name = nil @generator_options = [] @generators = RDoc::RDoc::GENERATORS @hyperlink_all = false @line_numbers = false @main_page = nil @markup = 'rdoc' @coverage_report = false @op_dir = nil @page_dir = nil @pipe = false @rdoc_include = [] @root = Pathname(Dir.pwd) @show_hash = false @static_path = [] @stylesheet_url = nil # TODO remove in RDoc 4 @tab_width = 8 @template = nil @template_dir = nil @title = nil @update_output_dir = true @verbosity = 1 @visibility = :protected @webcvs = nil @write_options = false if Object.const_defined? :Encoding then @encoding = Encoding::UTF_8 @charset = @encoding.name else @encoding = nil @charset = 'UTF-8' end end def init_with map # :nodoc: init_ivars encoding = map['encoding'] @encoding = if Object.const_defined? :Encoding then encoding ? Encoding.find(encoding) : encoding end @charset = map['charset'] @exclude = map['exclude'] @generator_name = map['generator_name'] @hyperlink_all = map['hyperlink_all'] @line_numbers = map['line_numbers'] @main_page = map['main_page'] @markup = map['markup'] @op_dir = map['op_dir'] @show_hash = map['show_hash'] @tab_width = map['tab_width'] @template_dir = map['template_dir'] @title = map['title'] @visibility = map['visibility'] @webcvs = map['webcvs'] @rdoc_include = sanitize_path map['rdoc_include'] @static_path = sanitize_path map['static_path'] end def yaml_initialize tag, map # :nodoc: init_with map end def == other # :nodoc: self.class === other and @encoding == other.encoding and @generator_name == other.generator_name and @hyperlink_all == other.hyperlink_all and @line_numbers == other.line_numbers and @main_page == other.main_page and @markup == other.markup and @op_dir == other.op_dir and @rdoc_include == other.rdoc_include and @show_hash == other.show_hash and @static_path == other.static_path and @tab_width == other.tab_width and @template == other.template and @title == other.title and @visibility == other.visibility and @webcvs == other.webcvs end ## # Check that the files on the command line exist def check_files @files.delete_if do |file| if File.exist? file then if File.readable? file then false else warn "file '#{file}' not readable" true end else warn "file '#{file}' not found" true end end end ## # Ensure only one generator is loaded def check_generator if @generator then raise OptionParser::InvalidOption, "generator already set to #{@generator_name}" end end ## # Set the title, but only if not already set. Used to set the title # from a source file, so that a title set from the command line # will have the priority. def default_title=(string) @title ||= string end ## # For dumping YAML def encode_with coder # :nodoc: encoding = @encoding ? @encoding.name : nil coder.add 'encoding', encoding coder.add 'static_path', sanitize_path(@static_path) coder.add 'rdoc_include', sanitize_path(@rdoc_include) ivars = instance_variables.map { |ivar| ivar.to_s[1..-1] } ivars -= SPECIAL ivars.sort.each do |ivar| coder.add ivar, instance_variable_get("@#{ivar}") end end ## # Completes any unfinished option setup business such as filtering for # existent files, creating a regexp for #exclude and setting a default # #template. def finish @op_dir ||= 'doc' @rdoc_include << "." if @rdoc_include.empty? if @exclude.nil? or Regexp === @exclude then # done, #finish is being re-run elsif @exclude.empty? then @exclude = nil else @exclude = Regexp.new(@exclude.join("|")) end finish_page_dir check_files # If no template was specified, use the default template for the output # formatter unless @template then @template = @generator_name @template_dir = template_dir_for @template end self end ## # Fixes the page_dir to be relative to the root_dir and adds the page_dir to # the files list. def finish_page_dir return unless @page_dir @files << @page_dir.to_s page_dir = @page_dir.expand_path.relative_path_from @root @page_dir = page_dir end ## # Returns a properly-space list of generators and their descriptions. def generator_descriptions lengths = [] generators = RDoc::RDoc::GENERATORS.map do |name, generator| lengths << name.length description = generator::DESCRIPTION if generator.const_defined? :DESCRIPTION [name, description] end longest = lengths.max generators.sort.map do |name, description| if description then " %-*s - %s" % [longest, name, description] else " #{name}" end end.join "\n" end ## # Parses command line options. def parse argv ignore_invalid = true argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT'] opts = OptionParser.new do |opt| @option_parser = opt opt.program_name = File.basename $0 opt.version = RDoc::VERSION opt.release = nil opt.summary_indent = ' ' * 4 opt.banner = <<-EOF Usage: #{opt.program_name} [options] [names...] Files are parsed, and the information they contain collected, before any output is produced. This allows cross references between all files to be resolved. If a name is a directory, it is traversed. If no names are specified, all Ruby files in the current directory (and subdirectories) are processed. How RDoc generates output depends on the output formatter being used, and on the options you give. Options can be specified via the RDOCOPT environment variable, which functions similar to the RUBYOPT environment variable for ruby. $ export RDOCOPT="--show-hash" will make rdoc show hashes in method links by default. Command-line options always will override those in RDOCOPT. Available formatters: #{generator_descriptions} RDoc understands the following file formats: EOF parsers = Hash.new { |h,parser| h[parser] = [] } RDoc::Parser.parsers.each do |regexp, parser| parsers[parser.name.sub('RDoc::Parser::', '')] << regexp.source end parsers.sort.each do |parser, regexp| opt.banner << " - #{parser}: #{regexp.join ', '}\n" end opt.banner << "\n The following options are deprecated:\n\n" name_length = DEPRECATED.keys.sort_by { |k| k.length }.last.length DEPRECATED.sort_by { |k,| k }.each do |name, reason| opt.banner << " %*1$2$s %3$s\n" % [-name_length, name, reason] end opt.accept Template do |template| template_dir = template_dir_for template unless template_dir then $stderr.puts "could not find template #{template}" nil else [template, template_dir] end end opt.accept Directory do |directory| directory = File.expand_path directory raise OptionParser::InvalidArgument unless File.directory? directory directory end opt.accept Path do |path| path = File.expand_path path raise OptionParser::InvalidArgument unless File.exist? path path end opt.accept PathArray do |paths,| paths = if paths then paths.split(',').map { |d| d unless d.empty? } end paths.map do |path| path = File.expand_path path raise OptionParser::InvalidArgument unless File.exist? path path end end opt.separator nil opt.separator "Parsing options:" opt.separator nil if Object.const_defined? :Encoding then opt.on("--encoding=ENCODING", "-e", Encoding.list.map { |e| e.name }, "Specifies the output encoding. All files", "read will be converted to this encoding.", "The default encoding is UTF-8.", "--encoding is preferred over --charset") do |value| @encoding = Encoding.find value @charset = @encoding.name # may not be valid value end opt.separator nil end opt.on("--all", "-a", "Synonym for --visibility=private.") do |value| @visibility = :private end opt.separator nil opt.on("--exclude=PATTERN", "-x", Regexp, "Do not process files or directories", "matching PATTERN.") do |value| @exclude << value end opt.separator nil opt.on("--extension=NEW=OLD", "-E", "Treat files ending with .new as if they", "ended with .old. Using '-E cgi=rb' will", "cause xxx.cgi to be parsed as a Ruby file.") do |value| new, old = value.split(/=/, 2) unless new and old then raise OptionParser::InvalidArgument, "Invalid parameter to '-E'" end unless RDoc::Parser.alias_extension old, new then raise OptionParser::InvalidArgument, "Unknown extension .#{old} to -E" end end opt.separator nil opt.on("--[no-]force-update", "-U", "Forces rdoc to scan all sources even if", "newer than the flag file.") do |value| @force_update = value end opt.separator nil opt.on("--pipe", "-p", "Convert RDoc on stdin to HTML") do @pipe = true end opt.separator nil opt.on("--tab-width=WIDTH", "-w", OptionParser::DecimalInteger, "Set the width of tab characters.") do |value| @tab_width = value end opt.separator nil opt.on("--visibility=VISIBILITY", "-V", RDoc::VISIBILITIES, "Minimum visibility to document a method.", "One of 'public', 'protected' (the default)", "or 'private'. Can be abbreviated.") do |value| @visibility = value end opt.separator nil markup_formats = RDoc::Text::MARKUP_FORMAT.keys.sort opt.on("--markup=MARKUP", markup_formats, "The markup format for the named files.", "The default is rdoc. Valid values are:", markup_formats.join(', ')) do |value| @markup = value end opt.separator nil opt.on("--root=ROOT", Directory, "Root of the source tree documentation", "will be generated for. Set this when", "building documentation outside the", "source directory. Default is the", "current directory.") do |root| @root = Pathname(root) end opt.separator nil opt.on("--page-dir=DIR", Directory, "Directory where guides, your FAQ or", "other pages not associated with a class", "live. Set this when you don't store", "such files at your project root.", "NOTE: Do not use the same file name in", "the page dir and the root of your project") do |page_dir| @page_dir = Pathname(page_dir) end opt.separator nil opt.separator "Common generator options:" opt.separator nil opt.on("--force-output", "-O", "Forces rdoc to write the output files,", "even if the output directory exists", "and does not seem to have been created", "by rdoc.") do |value| @force_output = value end opt.separator nil generator_text = @generators.keys.map { |name| " #{name}" }.sort opt.on("-f", "--fmt=FORMAT", "--format=FORMAT", @generators.keys, "Set the output formatter. One of:", *generator_text) do |value| check_generator @generator_name = value.downcase setup_generator end opt.separator nil opt.on("--include=DIRECTORIES", "-i", PathArray, "Set (or add to) the list of directories to", "be searched when satisfying :include:", "requests. Can be used more than once.") do |value| @rdoc_include.concat value.map { |dir| dir.strip } end opt.separator nil opt.on("--[no-]coverage-report=[LEVEL]", "--[no-]dcov", "-C", Integer, "Prints a report on undocumented items.", "Does not generate files.") do |value| value = 0 if value.nil? # Integer converts -C to nil @coverage_report = value @force_update = true if value end opt.separator nil opt.on("--output=DIR", "--op", "-o", "Set the output directory.") do |value| @op_dir = value end opt.separator nil opt.on("-d", "Deprecated --diagram option.", "Prevents firing debug mode", "with legacy invocation.") do |value| end opt.separator nil opt.separator 'HTML generator options:' opt.separator nil opt.on("--charset=CHARSET", "-c", "Specifies the output HTML character-set.", "Use --encoding instead of --charset if", "available.") do |value| @charset = value end opt.separator nil opt.on("--hyperlink-all", "-A", "Generate hyperlinks for all words that", "correspond to known methods, even if they", "do not start with '#' or '::' (legacy", "behavior).") do |value| @hyperlink_all = value end opt.separator nil opt.on("--main=NAME", "-m", "NAME will be the initial page displayed.") do |value| @main_page = value end opt.separator nil opt.on("--[no-]line-numbers", "-N", "Include line numbers in the source code.", "By default, only the number of the first", "line is displayed, in a leading comment.") do |value| @line_numbers = value end opt.separator nil opt.on("--show-hash", "-H", "A name of the form #name in a comment is a", "possible hyperlink to an instance method", "name. When displayed, the '#' is removed", "unless this option is specified.") do |value| @show_hash = value end opt.separator nil opt.on("--template=NAME", "-T", Template, "Set the template used when generating", "output. The default depends on the", "formatter used.") do |(template, template_dir)| @template = template @template_dir = template_dir end opt.separator nil opt.on("--title=TITLE", "-t", "Set TITLE as the title for HTML output.") do |value| @title = value end opt.separator nil opt.on("--copy-files=PATH", Path, "Specify a file or directory to copy static", "files from.", "If a file is given it will be copied into", "the output dir. If a directory is given the", "entire directory will be copied.", "You can use this multiple times") do |value| @static_path << value end opt.separator nil opt.on("--webcvs=URL", "-W", "Specify a URL for linking to a web frontend", "to CVS. If the URL contains a '\%s', the", "name of the current file will be", "substituted; if the URL doesn't contain a", "'\%s', the filename will be appended to it.") do |value| @webcvs = value end opt.separator nil opt.separator "ri generator options:" opt.separator nil opt.on("--ri", "-r", "Generate output for use by `ri`. The files", "are stored in the '.rdoc' directory under", "your home directory unless overridden by a", "subsequent --op parameter, so no special", "privileges are needed.") do |value| check_generator @generator_name = "ri" @op_dir ||= RDoc::RI::Paths::HOMEDIR setup_generator end opt.separator nil opt.on("--ri-site", "-R", "Generate output for use by `ri`. The files", "are stored in a site-wide directory,", "making them accessible to others, so", "special privileges are needed.") do |value| check_generator @generator_name = "ri" @op_dir = RDoc::RI::Paths::SITEDIR setup_generator end opt.separator nil opt.separator "Generic options:" opt.separator nil opt.on("--write-options", "Write .rdoc_options to the current", "directory with the given options. Not all", "options will be used. See RDoc::Options", "for details.") do |value| @write_options = true end opt.separator nil opt.on("--[no-]dry-run", "Don't write any files") do |value| @dry_run = value end opt.separator nil opt.on("-D", "--[no-]debug", "Displays lots on internal stuff.") do |value| $DEBUG_RDOC = value end opt.separator nil opt.on("--[no-]ignore-invalid", "Ignore invalid options and continue", "(default true).") do |value| ignore_invalid = value end opt.separator nil opt.on("--quiet", "-q", "Don't show progress as we parse.") do |value| @verbosity = 0 end opt.separator nil opt.on("--verbose", "-v", "Display extra progress as RDoc parses") do |value| @verbosity = 2 end opt.separator nil opt.on("--help", "Display this help") do RDoc::RDoc::GENERATORS.each_key do |generator| setup_generator generator end puts opt.help exit end opt.separator nil end setup_generator 'darkfish' if argv.grep(/\A(-f|--fmt|--format|-r|-R|--ri|--ri-site)\b/).empty? deprecated = [] invalid = [] begin opts.parse! argv rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e if DEPRECATED[e.args.first] then deprecated << e.args.first elsif %w[--format --ri -r --ri-site -R].include? e.args.first then raise else invalid << e.args.join(' ') end retry end unless @generator then @generator = RDoc::Generator::Darkfish @generator_name = 'darkfish' end if @pipe and not argv.empty? then @pipe = false invalid << '-p (with files)' end unless quiet then deprecated.each do |opt| $stderr.puts 'option ' << opt << ' is deprecated: ' << DEPRECATED[opt] end unless invalid.empty? then invalid = "invalid options: #{invalid.join ', '}" if ignore_invalid then $stderr.puts invalid $stderr.puts '(invalid options are ignored)' else $stderr.puts opts $stderr.puts invalid exit 1 end end end @files = argv.dup finish if @write_options then write_options exit end self end ## # Don't display progress as we process the files def quiet @verbosity.zero? end ## # Set quietness to +bool+ def quiet= bool @verbosity = bool ? 0 : 1 end ## # Removes directories from +path+ that are outside the current directory def sanitize_path path require 'pathname' dot = Pathname.new('.').expand_path path.reject do |item| path = Pathname.new(item).expand_path relative = path.relative_path_from(dot).to_s relative.start_with? '..' end end ## # Set up an output generator for the named +generator_name+. # # If the found generator responds to :setup_options it will be called with # the options instance. This allows generators to add custom options or set # default options. def setup_generator generator_name = @generator_name @generator = @generators[generator_name] unless @generator then raise OptionParser::InvalidArgument, "Invalid output formatter #{generator_name}" end return if @generator_options.include? @generator @generator_name = generator_name @generator_options << @generator if @generator.respond_to? :setup_options then @option_parser ||= OptionParser.new @generator.setup_options self end end ## # Finds the template dir for +template+ def template_dir_for template template_path = File.join 'rdoc', 'generator', 'template', template $LOAD_PATH.map do |path| File.join File.expand_path(path), template_path end.find do |dir| File.directory? dir end end ## # This is compatibility code for syck def to_yaml opts = {} # :nodoc: return super if YAML.const_defined?(:ENGINE) and not YAML::ENGINE.syck? YAML.quick_emit self, opts do |out| out.map taguri, to_yaml_style do |map| encode_with map end end end ## # Displays a warning using Kernel#warn if we're being verbose def warn message super message if @verbosity > 1 end ## # Writes the YAML file .rdoc_options to the current directory containing the # parsed options. def write_options RDoc.load_yaml open '.rdoc_options', 'w' do |io| io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding YAML.dump self, io end end end rdoc/parser.rb000064400000017516147635155430007343 0ustar00# -*- coding: us-ascii -*- ## # A parser is simple a class that subclasses RDoc::Parser and implements #scan # to fill in an RDoc::TopLevel with parsed data. # # The initialize method takes an RDoc::TopLevel to fill with parsed content, # the name of the file to be parsed, the content of the file, an RDoc::Options # object and an RDoc::Stats object to inform the user of parsed items. The # scan method is then called to parse the file and must return the # RDoc::TopLevel object. By calling super these items will be set for you. # # In order to be used by RDoc the parser needs to register the file extensions # it can parse. Use ::parse_files_matching to register extensions. # # require 'rdoc' # # class RDoc::Parser::Xyz < RDoc::Parser # parse_files_matching /\.xyz$/ # # def initialize top_level, file_name, content, options, stats # super # # # extra initialization if needed # end # # def scan # # parse file and fill in @top_level # end # end class RDoc::Parser @parsers = [] class << self ## # An Array of arrays that maps file extension (or name) regular # expressions to parser classes that will parse matching filenames. # # Use parse_files_matching to register a parser's file extensions. attr_reader :parsers end ## # The name of the file being parsed attr_reader :file_name ## # Alias an extension to another extension. After this call, files ending # "new_ext" will be parsed using the same parser as "old_ext" def self.alias_extension(old_ext, new_ext) old_ext = old_ext.sub(/^\.(.*)/, '\1') new_ext = new_ext.sub(/^\.(.*)/, '\1') parser = can_parse_by_name "xxx.#{old_ext}" return false unless parser RDoc::Parser.parsers.unshift [/\.#{new_ext}$/, parser] true end ## # Determines if the file is a "binary" file which basically means it has # content that an RDoc parser shouldn't try to consume. def self.binary?(file) return false if file =~ /\.(rdoc|txt)$/ s = File.read(file, 1024) or return false have_encoding = s.respond_to? :encoding return true if s[0, 2] == Marshal.dump('')[0, 2] or s.index("\x00") if have_encoding then mode = "r" s.sub!(/\A#!.*\n/, '') # assume shebang line isn't longer than 1024. encoding = s[/^\s*\#\s*(?:-\*-\s*)?(?:en)?coding:\s*([^\s;]+?)(?:-\*-|[\s;])/, 1] mode = "r:#{encoding}" if encoding s = File.open(file, mode) {|f| f.gets(nil, 1024)} not s.valid_encoding? else if 0.respond_to? :fdiv then s.count("\x00-\x7F", "^ -~\t\r\n").fdiv(s.size) > 0.3 else # HACK 1.8.6 (s.count("\x00-\x7F", "^ -~\t\r\n").to_f / s.size) > 0.3 end end end ## # Processes common directives for CodeObjects for the C and Ruby parsers. # # Applies +directive+'s +value+ to +code_object+, if appropriate def self.process_directive code_object, directive, value warn "RDoc::Parser::process_directive is deprecated and wil be removed in RDoc 4. Use RDoc::Markup::PreProcess#handle_directive instead" if $-w case directive when 'nodoc' then code_object.document_self = nil # notify nodoc code_object.document_children = value.downcase != 'all' when 'doc' then code_object.document_self = true code_object.force_documentation = true when 'yield', 'yields' then # remove parameter &block code_object.params.sub!(/,?\s*&\w+/, '') if code_object.params code_object.block_params = value when 'arg', 'args' then code_object.params = value end end ## # Checks if +file+ is a zip file in disguise. Signatures from # http://www.garykessler.net/library/file_sigs.html def self.zip? file zip_signature = File.read file, 4 zip_signature == "PK\x03\x04" or zip_signature == "PK\x05\x06" or zip_signature == "PK\x07\x08" rescue false end ## # Return a parser that can handle a particular extension def self.can_parse file_name parser = can_parse_by_name file_name # HACK Selenium hides a jar file using a .txt extension return if parser == RDoc::Parser::Simple and zip? file_name parser end ## # Returns a parser that can handle the extension for +file_name+. This does # not depend upon the file being readable. def self.can_parse_by_name file_name _, parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name } # The default parser must not parse binary files ext_name = File.extname file_name return parser if ext_name.empty? if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/ then case check_modeline file_name when nil, 'rdoc' then # continue else return nil end end parser rescue Errno::EACCES end ## # Returns the file type from the modeline in +file_name+ def self.check_modeline file_name line = open file_name do |io| io.gets end /-\*-\s*(.*?\S)\s*-\*-/ =~ line return nil unless type = $1 if /;/ =~ type then return nil unless /(?:\s|\A)mode:\s*([^\s;]+)/i =~ type type = $1 end return nil if /coding:/i =~ type type.downcase rescue ArgumentError # invalid byte sequence, etc. end ## # Finds and instantiates the correct parser for the given +file_name+ and # +content+. def self.for top_level, file_name, content, options, stats return if binary? file_name parser = use_markup content unless parser then parse_name = file_name # If no extension, look for shebang if file_name !~ /\.\w+$/ && content =~ %r{\A#!(.+)} then shebang = $1 case shebang when %r{env\s+ruby}, %r{/ruby} parse_name = 'dummy.rb' end end parser = can_parse parse_name end return unless parser parser.new top_level, file_name, content, options, stats rescue SystemCallError nil end ## # Record which file types this parser can understand. # # It is ok to call this multiple times. def self.parse_files_matching(regexp) RDoc::Parser.parsers.unshift [regexp, self] end ## # If there is a markup: parser_name comment at the front of the # file, use it to determine the parser. For example: # # # markup: rdoc # # Class comment can go here # # class C # end # # The comment should appear as the first line of the +content+. # # If the content contains a shebang or editor modeline the comment may # appear on the second or third line. # # Any comment style may be used to hide the markup comment. def self.use_markup content markup = content.lines.first(3).grep(/markup:\s+(\w+)/) { $1 }.first return unless markup # TODO Ruby should be returned only when the filename is correct return RDoc::Parser::Ruby if %w[tomdoc markdown].include? markup markup = Regexp.escape markup RDoc::Parser.parsers.find do |_, parser| /^#{markup}$/i =~ parser.name.sub(/.*:/, '') end.last end ## # Creates a new Parser storing +top_level+, +file_name+, +content+, # +options+ and +stats+ in instance variables. In +@preprocess+ an # RDoc::Markup::PreProcess object is created which allows processing of # directives. def initialize top_level, file_name, content, options, stats @top_level = top_level @top_level.parser = self.class @store = @top_level.store @file_name = file_name @content = content @options = options @stats = stats @preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include @preprocess.options = @options end autoload :RubyTools, 'rdoc/parser/ruby_tools' autoload :Text, 'rdoc/parser/text' end # simple must come first in order to show up last in the parsers list require 'rdoc/parser/simple' require 'rdoc/parser/c' require 'rdoc/parser/changelog' require 'rdoc/parser/markdown' require 'rdoc/parser/rd' require 'rdoc/parser/ruby' rdoc/ri/paths.rb000064400000011341147635155430007566 0ustar00require 'rdoc/ri' ## # The directories where ri data lives. Paths can be enumerated via ::each, or # queried individually via ::system_dir, ::site_dir, ::home_dir and ::gem_dir. module RDoc::RI::Paths #:stopdoc: require 'rbconfig' version = RbConfig::CONFIG['ruby_version'] BASE = if RbConfig::CONFIG.key? 'ridir' then File.join RbConfig::CONFIG['ridir'], version else File.join RbConfig::CONFIG['datadir'], 'ri', version end homedir = begin File.expand_path('~') rescue ArgumentError end homedir ||= ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH'] # for 1.8 compatibility HOMEDIR = if homedir then File.join homedir, ".rdoc" end #:startdoc: ## # Iterates over each selected path yielding the directory and type. # # Yielded types: # :system:: Where Ruby's ri data is stored. Yielded when +system+ is # true # :site:: Where ri for installed libraries are stored. Yielded when # +site+ is true. Normally no ri data is stored here. # :home:: ~/.rdoc. Yielded when +home+ is true. # :gem:: ri data for an installed gem. Yielded when +gems+ is true. # :extra:: ri data directory from the command line. Yielded for each # entry in +extra_dirs+ def self.each system = true, site = true, home = true, gems = :latest, *extra_dirs # :yields: directory, type return enum_for __method__, system, site, home, gems, *extra_dirs unless block_given? extra_dirs.each do |dir| yield dir, :extra end yield system_dir, :system if system yield site_dir, :site if site yield home_dir, :home if home and HOMEDIR gemdirs(gems).each do |dir| yield dir, :gem end if gems nil end ## # The ri directory for the gem with +gem_name+. def self.gem_dir name, version req = Gem::Requirement.new "= #{version}" spec = Gem::Specification.find_by_name name, req File.join spec.doc_dir, 'ri' end ## # The latest installed gems' ri directories. +filter+ can be :all or # :latest. # # A +filter+ :all includes all versions of gems and includes gems without # ri documentation. def self.gemdirs filter = :latest require 'rubygems' unless defined?(Gem) ri_paths = {} all = Gem::Specification.map do |spec| [File.join(spec.doc_dir, 'ri'), spec.name, spec.version] end if filter == :all then gemdirs = [] all.group_by do |_, name, _| name end.sort_by do |group, _| group end.map do |group, items| items.sort_by do |_, _, version| version end.reverse_each do |dir,| gemdirs << dir end end return gemdirs end all.each do |dir, name, ver| next unless File.exist? dir if ri_paths[name].nil? or ver > ri_paths[name].first then ri_paths[name] = [ver, name, dir] end end ri_paths.sort_by { |_, (_, name, _)| name }.map { |k, v| v.last } rescue LoadError [] end ## # The location of the rdoc data in the user's home directory. # # Like ::system, ri data in the user's home directory is rare and predates # libraries distributed via RubyGems. ri data is rarely generated into this # directory. def self.home_dir HOMEDIR end ## # Returns existing directories from the selected documentation directories # as an Array. # # See also ::each def self.path(system = true, site = true, home = true, gems = :latest, *extra_dirs) path = raw_path system, site, home, gems, *extra_dirs path.select { |directory| File.directory? directory } end ## # Returns selected documentation directories including nonexistent # directories. # # See also ::each def self.raw_path(system, site, home, gems, *extra_dirs) path = [] each(system, site, home, gems, *extra_dirs) do |dir, type| path << dir end path.compact end ## # The location of ri data installed into the site dir. # # Historically this was available for documentation installed by ruby # libraries predating RubyGems. It is unlikely to contain any content for # modern ruby installations. def self.site_dir File.join BASE, 'site' end ## # The location of the built-in ri data. # # This data is built automatically when `make` is run when ruby is # installed. If you did not install ruby by hand you may need to install # the documentation yourself. Please consult the documentation for your # package manager or ruby installer for details. You can also use the # rdoc-data gem to install system ri data for common versions of ruby. def self.system_dir File.join BASE, 'system' end end rdoc/ri/store.rb000064400000000067147635155430007606 0ustar00module RDoc::RI Store = RDoc::Store # :nodoc: end rdoc/ri/formatter.rb000064400000000124147635155430010447 0ustar00## # For RubyGems backwards compatibility module RDoc::RI::Formatter # :nodoc: end rdoc/ri/driver.rb000064400000101341147635155430007742 0ustar00require 'abbrev' require 'optparse' begin require 'readline' rescue LoadError end begin require 'win32console' rescue LoadError end require 'rdoc' ## # For RubyGems backwards compatibility require 'rdoc/ri/formatter' ## # The RI driver implements the command-line ri tool. # # The driver supports: # * loading RI data from: # * Ruby's standard library # * RubyGems # * ~/.rdoc # * A user-supplied directory # * Paging output (uses RI_PAGER environment variable, PAGER environment # variable or the less, more and pager programs) # * Interactive mode with tab-completion # * Abbreviated names (ri Zl shows Zlib documentation) # * Colorized output # * Merging output from multiple RI data sources class RDoc::RI::Driver ## # Base Driver error class class Error < RDoc::RI::Error; end ## # Raised when a name isn't found in the ri data stores class NotFoundError < Error ## # Name that wasn't found alias name message def message # :nodoc: "Nothing known about #{super}" end end ## # Show all method documentation following a class or module attr_accessor :show_all ## # An RDoc::RI::Store for each entry in the RI path attr_accessor :stores ## # Controls the user of the pager vs $stdout attr_accessor :use_stdout ## # Default options for ri def self.default_options options = {} options[:interactive] = false options[:profile] = false options[:show_all] = false options[:use_cache] = true options[:use_stdout] = !$stdout.tty? options[:width] = 72 # By default all standard paths are used. options[:use_system] = true options[:use_site] = true options[:use_home] = true options[:use_gems] = true options[:extra_doc_dirs] = [] return options end ## # Dump +data_path+ using pp def self.dump data_path require 'pp' open data_path, 'rb' do |io| pp Marshal.load(io.read) end end ## # Parses +argv+ and returns a Hash of options def self.process_args argv options = default_options opts = OptionParser.new do |opt| opt.accept File do |file,| File.readable?(file) and not File.directory?(file) and file end opt.program_name = File.basename $0 opt.version = RDoc::VERSION opt.release = nil opt.summary_indent = ' ' * 4 opt.banner = <<-EOT Usage: #{opt.program_name} [options] [names...] Where name can be: Class | Module | Module::Class Class::method | Class#method | Class.method | method gem_name: | gem_name:README | gem_name:History All class names may be abbreviated to their minimum unambiguous form. If a name is ambiguous, all valid options will be listed. A '.' matches either class or instance methods, while #method matches only instance and ::method matches only class methods. README and other files may be displayed by prefixing them with the gem name they're contained in. If the gem name is followed by a ':' all files in the gem will be shown. The file name extension may be omitted where it is unambiguous. For example: #{opt.program_name} Fil #{opt.program_name} File #{opt.program_name} File.new #{opt.program_name} zip #{opt.program_name} rdoc:README Note that shell quoting or escaping may be required for method names containing punctuation: #{opt.program_name} 'Array.[]' #{opt.program_name} compact\\! To see the default directories ri will search, run: #{opt.program_name} --list-doc-dirs Specifying the --system, --site, --home, --gems or --doc-dir options will limit ri to searching only the specified directories. ri options may be set in the 'RI' environment variable. The ri pager can be set with the 'RI_PAGER' environment variable or the 'PAGER' environment variable. EOT opt.separator nil opt.separator "Options:" opt.separator nil opt.on("--[no-]interactive", "-i", "In interactive mode you can repeatedly", "look up methods with autocomplete.") do |interactive| options[:interactive] = interactive end opt.separator nil opt.on("--[no-]all", "-a", "Show all documentation for a class or", "module.") do |show_all| options[:show_all] = show_all end opt.separator nil opt.on("--[no-]list", "-l", "List classes ri knows about.") do |list| options[:list] = list end opt.separator nil opt.on("--[no-]pager", "-T", "Send output directly to stdout,", "rather than to a pager.") do |use_pager| options[:use_stdout] = !use_pager end opt.separator nil opt.on("--width=WIDTH", "-w", OptionParser::DecimalInteger, "Set the width of the output.") do |width| options[:width] = width end opt.separator nil opt.on("--server [PORT]", Integer, "Run RDoc server on the given port.", "The default port is 8214.") do |port| options[:server] = port || 8214 end opt.separator nil formatters = RDoc::Markup.constants.grep(/^To[A-Z][a-z]+$/).sort formatters = formatters.sort.map do |formatter| formatter.to_s.sub('To', '').downcase end formatters -= %w[html label test] # remove useless output formats opt.on("--format=NAME", "-f", "Uses the selected formatter. The default", "formatter is bs for paged output and ansi", "otherwise. Valid formatters are:", formatters.join(' '), formatters) do |value| options[:formatter] = RDoc::Markup.const_get "To#{value.capitalize}" end opt.separator nil opt.separator "Data source options:" opt.separator nil opt.on("--[no-]list-doc-dirs", "List the directories from which ri will", "source documentation on stdout and exit.") do |list_doc_dirs| options[:list_doc_dirs] = list_doc_dirs end opt.separator nil opt.on("--doc-dir=DIRNAME", "-d", Array, "List of directories from which to source", "documentation in addition to the standard", "directories. May be repeated.") do |value| value.each do |dir| unless File.directory? dir then raise OptionParser::InvalidArgument, "#{dir} is not a directory" end options[:extra_doc_dirs] << File.expand_path(dir) end end opt.separator nil opt.on("--no-standard-docs", "Do not include documentation from", "the Ruby standard library, site_lib,", "installed gems, or ~/.rdoc.", "Use with --doc-dir") do options[:use_system] = false options[:use_site] = false options[:use_gems] = false options[:use_home] = false end opt.separator nil opt.on("--[no-]system", "Include documentation from Ruby's standard", "library. Defaults to true.") do |value| options[:use_system] = value end opt.separator nil opt.on("--[no-]site", "Include documentation from libraries", "installed in site_lib.", "Defaults to true.") do |value| options[:use_site] = value end opt.separator nil opt.on("--[no-]gems", "Include documentation from RubyGems.", "Defaults to true.") do |value| options[:use_gems] = value end opt.separator nil opt.on("--[no-]home", "Include documentation stored in ~/.rdoc.", "Defaults to true.") do |value| options[:use_home] = value end opt.separator nil opt.separator "Debug options:" opt.separator nil opt.on("--[no-]profile", "Run with the ruby profiler") do |value| options[:profile] = value end opt.separator nil opt.on("--dump=CACHE", File, "Dumps data from an ri cache or data file") do |value| options[:dump_path] = value end end argv = ENV['RI'].to_s.split.concat argv opts.parse! argv options[:names] = argv options[:use_stdout] ||= !$stdout.tty? options[:use_stdout] ||= options[:interactive] options[:width] ||= 72 options rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e puts opts puts puts e exit 1 end ## # Runs the ri command line executable using +argv+ def self.run argv = ARGV options = process_args argv if options[:dump_path] then dump options[:dump_path] return end ri = new options ri.run end ## # Creates a new driver using +initial_options+ from ::process_args def initialize initial_options = {} @paging = false @classes = nil options = self.class.default_options.update(initial_options) @formatter_klass = options[:formatter] require 'profile' if options[:profile] @names = options[:names] @list = options[:list] @doc_dirs = [] @stores = [] RDoc::RI::Paths.each(options[:use_system], options[:use_site], options[:use_home], options[:use_gems], *options[:extra_doc_dirs]) do |path, type| @doc_dirs << path store = RDoc::RI::Store.new path, type store.load_cache @stores << store end @list_doc_dirs = options[:list_doc_dirs] @interactive = options[:interactive] @server = options[:server] @use_stdout = options[:use_stdout] @show_all = options[:show_all] # pager process for jruby @jruby_pager_process = nil end ## # Adds paths for undocumented classes +also_in+ to +out+ def add_also_in out, also_in return if also_in.empty? out << RDoc::Markup::Rule.new(1) out << RDoc::Markup::Paragraph.new("Also found in:") paths = RDoc::Markup::Verbatim.new also_in.each do |store| paths.parts.push store.friendly_path, "\n" end out << paths end ## # Adds a class header to +out+ for class +name+ which is described in # +classes+. def add_class out, name, classes heading = if classes.all? { |klass| klass.module? } then name else superclass = classes.map do |klass| klass.superclass unless klass.module? end.compact.shift || 'Object' superclass = superclass.full_name unless String === superclass "#{name} < #{superclass}" end out << RDoc::Markup::Heading.new(1, heading) out << RDoc::Markup::BlankLine.new end ## # Adds "(from ...)" to +out+ for +store+ def add_from out, store out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})") end ## # Adds +extends+ to +out+ def add_extends out, extends add_extension_modules out, 'Extended by', extends end ## # Adds a list of +extensions+ to this module of the given +type+ to +out+. # add_includes and add_extends call this, so you should use those directly. def add_extension_modules out, type, extensions return if extensions.empty? out << RDoc::Markup::Rule.new(1) out << RDoc::Markup::Heading.new(1, "#{type}:") extensions.each do |modules, store| if modules.length == 1 then include = modules.first name = include.name path = store.friendly_path out << RDoc::Markup::Paragraph.new("#{name} (from #{path})") if include.comment then out << RDoc::Markup::BlankLine.new out << include.comment end else out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})") wout, with = modules.partition { |incl| incl.comment.empty? } out << RDoc::Markup::BlankLine.new unless with.empty? with.each do |incl| out << RDoc::Markup::Paragraph.new(incl.name) out << RDoc::Markup::BlankLine.new out << incl.comment end unless wout.empty? then verb = RDoc::Markup::Verbatim.new wout.each do |incl| verb.push incl.name, "\n" end out << verb end end end end ## # Adds +includes+ to +out+ def add_includes out, includes add_extension_modules out, 'Includes', includes end ## # Looks up the method +name+ and adds it to +out+ def add_method out, name filtered = lookup_method name method_out = method_document name, filtered out.concat method_out.parts end ## # Adds documentation for all methods in +klass+ to +out+ def add_method_documentation out, klass klass.method_list.each do |method| begin add_method out, method.full_name rescue NotFoundError next end end end ## # Adds a list of +methods+ to +out+ with a heading of +name+ def add_method_list out, methods, name return if methods.empty? out << RDoc::Markup::Heading.new(1, "#{name}:") out << RDoc::Markup::BlankLine.new if @use_stdout and !@interactive then out.concat methods.map { |method| RDoc::Markup::Verbatim.new method } else out << RDoc::Markup::IndentedParagraph.new(2, methods.join(', ')) end out << RDoc::Markup::BlankLine.new end ## # Returns ancestor classes of +klass+ def ancestors_of klass ancestors = [] unexamined = [klass] seen = [] loop do break if unexamined.empty? current = unexamined.shift seen << current stores = classes[current] break unless stores and not stores.empty? klasses = stores.map do |store| store.ancestors[current] end.flatten.uniq klasses = klasses - seen ancestors.concat klasses unexamined.concat klasses end ancestors.reverse end ## # For RubyGems backwards compatibility def class_cache # :nodoc: end ## # Builds a RDoc::Markup::Document from +found+, +klasess+ and +includes+ def class_document name, found, klasses, includes, extends also_in = [] out = RDoc::Markup::Document.new add_class out, name, klasses add_includes out, includes add_extends out, extends found.each do |store, klass| comment = klass.comment # TODO the store's cache should always return an empty Array class_methods = store.class_methods[klass.full_name] || [] instance_methods = store.instance_methods[klass.full_name] || [] attributes = store.attributes[klass.full_name] || [] if comment.empty? and instance_methods.empty? and class_methods.empty? then also_in << store next end add_from out, store unless comment.empty? then out << RDoc::Markup::Rule.new(1) if comment.merged? then parts = comment.parts parts = parts.zip [RDoc::Markup::BlankLine.new] * parts.length parts.flatten! parts.pop out.concat parts else out << comment end end if class_methods or instance_methods or not klass.constants.empty? then out << RDoc::Markup::Rule.new(1) end unless klass.constants.empty? then out << RDoc::Markup::Heading.new(1, "Constants:") out << RDoc::Markup::BlankLine.new list = RDoc::Markup::List.new :NOTE constants = klass.constants.sort_by { |constant| constant.name } list.items.concat constants.map { |constant| parts = constant.comment.parts if constant.comment parts << RDoc::Markup::Paragraph.new('[not documented]') if parts.empty? RDoc::Markup::ListItem.new(constant.name, *parts) } out << list out << RDoc::Markup::BlankLine.new end add_method_list out, class_methods, 'Class methods' add_method_list out, instance_methods, 'Instance methods' add_method_list out, attributes, 'Attributes' add_method_documentation out, klass if @show_all end add_also_in out, also_in out end ## # Hash mapping a known class or module to the stores it can be loaded from def classes return @classes if @classes @classes = {} @stores.each do |store| store.cache[:modules].each do |mod| # using default block causes searched-for modules to be added @classes[mod] ||= [] @classes[mod] << store end end @classes end ## # Returns the stores wherein +name+ is found along with the classes, # extends and includes that match it def classes_and_includes_and_extends_for name klasses = [] extends = [] includes = [] found = @stores.map do |store| begin klass = store.load_class name klasses << klass extends << [klass.extends, store] if klass.extends includes << [klass.includes, store] if klass.includes [store, klass] rescue RDoc::Store::MissingFileError end end.compact extends.reject! do |modules,| modules.empty? end includes.reject! do |modules,| modules.empty? end [found, klasses, includes, extends] end ## # Completes +name+ based on the caches. For Readline def complete name klasses = classes.keys completions = [] klass, selector, method = parse_name name # may need to include Foo when given Foo:: klass_name = method ? name : klass if name !~ /#|\./ then completions = klasses.grep(/^#{Regexp.escape klass_name}[^:]*$/) completions.concat klasses.grep(/^#{Regexp.escape name}[^:]*$/) if name =~ /::$/ completions << klass if classes.key? klass # to complete a method name elsif selector then completions << klass if classes.key? klass elsif classes.key? klass_name then completions << klass_name end if completions.include? klass and name =~ /#|\.|::/ then methods = list_methods_matching name if not methods.empty? then # remove Foo if given Foo:: and a method was found completions.delete klass elsif selector then # replace Foo with Foo:: as given completions.delete klass completions << "#{klass}#{selector}" end completions.concat methods end completions.sort.uniq end ## # Converts +document+ to text and writes it to the pager def display document page do |io| text = document.accept formatter(io) io.write text end end ## # Outputs formatted RI data for class +name+. Groups undocumented classes def display_class name return if name =~ /#|\./ found, klasses, includes, extends = classes_and_includes_and_extends_for name return if found.empty? out = class_document name, found, klasses, includes, extends display out end ## # Outputs formatted RI data for method +name+ def display_method name out = RDoc::Markup::Document.new add_method out, name display out end ## # Outputs formatted RI data for the class or method +name+. # # Returns true if +name+ was found, false if it was not an alternative could # be guessed, raises an error if +name+ couldn't be guessed. def display_name name if name =~ /\w:(\w|$)/ then display_page name return true end return true if display_class name display_method name if name =~ /::|#|\./ true rescue NotFoundError matches = list_methods_matching name if name =~ /::|#|\./ matches = classes.keys.grep(/^#{name}/) if matches.empty? raise if matches.empty? page do |io| io.puts "#{name} not found, maybe you meant:" io.puts io.puts matches.sort.join("\n") end false end ## # Displays each name in +name+ def display_names names names.each do |name| name = expand_name name display_name name end end ## # Outputs formatted RI data for page +name+. def display_page name store_name, page_name = name.split ':', 2 store = @stores.find { |s| s.source == store_name } return display_page_list store if page_name.empty? pages = store.cache[:pages] unless pages.include? page_name then found_names = pages.select do |n| n =~ /#{Regexp.escape page_name}\.[^.]+$/ end if found_names.length.zero? then return display_page_list store, pages elsif found_names.length > 1 then return display_page_list store, found_names, page_name end page_name = found_names.first end page = store.load_page page_name display page.comment end ## # Outputs a formatted RI page list for the pages in +store+. def display_page_list store, pages = store.cache[:pages], search = nil out = RDoc::Markup::Document.new title = if search then "#{search} pages" else 'Pages' end out << RDoc::Markup::Heading.new(1, "#{title} in #{store.friendly_path}") out << RDoc::Markup::BlankLine.new list = RDoc::Markup::List.new(:BULLET) pages.each do |page| list << RDoc::Markup::Paragraph.new(page) end out << list display out end ## # Expands abbreviated klass +klass+ into a fully-qualified class. "Zl::Da" # will be expanded to Zlib::DataError. def expand_class klass klass.split('::').inject '' do |expanded, klass_part| expanded << '::' unless expanded.empty? short = expanded << klass_part subset = classes.keys.select do |klass_name| klass_name =~ /^#{expanded}[^:]*$/ end abbrevs = Abbrev.abbrev subset expanded = abbrevs[short] raise NotFoundError, short unless expanded expanded.dup end end ## # Expands the class portion of +name+ into a fully-qualified class. See # #expand_class. def expand_name name klass, selector, method = parse_name name return [selector, method].join if klass.empty? case selector when ':' then [find_store(klass), selector, method] else [expand_class(klass), selector, method] end.join end ## # Filters the methods in +found+ trying to find a match for +name+. def filter_methods found, name regexp = name_regexp name filtered = found.find_all do |store, methods| methods.any? { |method| method.full_name =~ regexp } end return filtered unless filtered.empty? found end ## # Yields items matching +name+ including the store they were found in, the # class being searched for, the class they were found in (an ancestor) the # types of methods to look up (from #method_type), and the method name being # searched for def find_methods name klass, selector, method = parse_name name types = method_type selector klasses = nil ambiguous = klass.empty? if ambiguous then klasses = classes.keys else klasses = ancestors_of klass klasses.unshift klass end methods = [] klasses.each do |ancestor| ancestors = classes[ancestor] next unless ancestors klass = ancestor if ambiguous ancestors.each do |store| methods << [store, klass, ancestor, types, method] end end methods = methods.sort_by do |_, k, a, _, m| [k, a, m].compact end methods.each do |item| yield(*item) # :yields: store, klass, ancestor, types, method end self end ## # Finds the given +pager+ for jruby. Returns an IO if +pager+ was found. # # Returns false if +pager+ does not exist. # # Returns nil if the jruby JVM doesn't support ProcessBuilder redirection # (1.6 and older). def find_pager_jruby pager require 'java' require 'shellwords' return nil unless java.lang.ProcessBuilder.constants.include? :Redirect pager = Shellwords.split pager pb = java.lang.ProcessBuilder.new(*pager) pb = pb.redirect_output java.lang.ProcessBuilder::Redirect::INHERIT @jruby_pager_process = pb.start input = @jruby_pager_process.output_stream io = input.to_io io.sync = true io rescue java.io.IOException false end ## # Finds a store that matches +name+ which can be the name of a gem, "ruby", # "home" or "site". # # See also RDoc::Store#source def find_store name @stores.each do |store| source = store.source return source if source == name return source if store.type == :gem and source =~ /^#{Regexp.escape name}-\d/ end raise RDoc::RI::Driver::NotFoundError, name end ## # Creates a new RDoc::Markup::Formatter. If a formatter is given with -f, # use it. If we're outputting to a pager, use bs, otherwise ansi. def formatter(io) if @formatter_klass then @formatter_klass.new elsif paging? or !io.tty? then RDoc::Markup::ToBs.new else RDoc::Markup::ToAnsi.new end end ## # Runs ri interactively using Readline if it is available. def interactive puts "\nEnter the method name you want to look up." if defined? Readline then Readline.completion_proc = method :complete puts "You can use tab to autocomplete." end puts "Enter a blank line to exit.\n\n" loop do name = if defined? Readline then Readline.readline ">> " else print ">> " $stdin.gets end return if name.nil? or name.empty? name = expand_name name.strip begin display_name name rescue NotFoundError => e puts e.message end end rescue Interrupt exit end ## # Is +file+ in ENV['PATH']? def in_path? file return true if file =~ %r%\A/% and File.exist? file ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path| File.exist? File.join(path, file) end end ## # Lists classes known to ri starting with +names+. If +names+ is empty all # known classes are shown. def list_known_classes names = [] classes = [] stores.each do |store| classes << store.module_names end classes = classes.flatten.uniq.sort unless names.empty? then filter = Regexp.union names.map { |name| /^#{name}/ } classes = classes.grep filter end page do |io| if paging? or io.tty? then if names.empty? then io.puts "Classes and Modules known to ri:" else io.puts "Classes and Modules starting with #{names.join ', '}:" end io.puts end io.puts classes.join("\n") end end ## # Returns an Array of methods matching +name+ def list_methods_matching name found = [] find_methods name do |store, klass, ancestor, types, method| if types == :instance or types == :both then methods = store.instance_methods[ancestor] if methods then matches = methods.grep(/^#{Regexp.escape method.to_s}/) matches = matches.map do |match| "#{klass}##{match}" end found.concat matches end end if types == :class or types == :both then methods = store.class_methods[ancestor] next unless methods matches = methods.grep(/^#{Regexp.escape method.to_s}/) matches = matches.map do |match| "#{klass}::#{match}" end found.concat matches end end found.uniq end ## # Loads RI data for method +name+ on +klass+ from +store+. +type+ and # +cache+ indicate if it is a class or instance method. def load_method store, cache, klass, type, name methods = store.send(cache)[klass] return unless methods method = methods.find do |method_name| method_name == name end return unless method store.load_method klass, "#{type}#{method}" end ## # Returns an Array of RI data for methods matching +name+ def load_methods_matching name found = [] find_methods name do |store, klass, ancestor, types, method| methods = [] methods << load_method(store, :class_methods, ancestor, '::', method) if [:class, :both].include? types methods << load_method(store, :instance_methods, ancestor, '#', method) if [:instance, :both].include? types found << [store, methods.compact] end found.reject do |path, methods| methods.empty? end end ## # Returns a filtered list of methods matching +name+ def lookup_method name found = load_methods_matching name raise NotFoundError, name if found.empty? filter_methods found, name end ## # Builds a RDoc::Markup::Document from +found+, +klasses+ and +includes+ def method_document name, filtered out = RDoc::Markup::Document.new out << RDoc::Markup::Heading.new(1, name) out << RDoc::Markup::BlankLine.new filtered.each do |store, methods| methods.each do |method| out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})") unless name =~ /^#{Regexp.escape method.parent_name}/ then out << RDoc::Markup::Heading.new(3, "Implementation from #{method.parent_name}") end out << RDoc::Markup::Rule.new(1) if method.arglists then arglists = method.arglists.chomp.split "\n" arglists = arglists.map { |line| line + "\n" } out << RDoc::Markup::Verbatim.new(*arglists) out << RDoc::Markup::Rule.new(1) end if method.respond_to?(:superclass_method) and method.superclass_method out << RDoc::Markup::BlankLine.new out << RDoc::Markup::Heading.new(4, "(Uses superclass method #{method.superclass_method})") out << RDoc::Markup::Rule.new(1) end out << RDoc::Markup::BlankLine.new out << method.comment out << RDoc::Markup::BlankLine.new end end out end ## # Returns the type of method (:both, :instance, :class) for +selector+ def method_type selector case selector when '.', nil then :both when '#' then :instance else :class end end ## # Returns a regular expression for +name+ that will match an # RDoc::AnyMethod's name. def name_regexp name klass, type, name = parse_name name case type when '#', '::' then /^#{klass}#{type}#{Regexp.escape name}$/ else /^#{klass}(#|::)#{Regexp.escape name}$/ end end ## # Paginates output through a pager program. def page if pager = setup_pager then begin yield pager ensure pager.close @jruby_pager_process.wait_for if @jruby_pager_process end else yield $stdout end rescue Errno::EPIPE ensure @paging = false end ## # Are we using a pager? def paging? @paging end ## # Extracts the class, selector and method name parts from +name+ like # Foo::Bar#baz. # # NOTE: Given Foo::Bar, Bar is considered a class even though it may be a # method def parse_name name parts = name.split(/(::?|#|\.)/) if parts.length == 1 then if parts.first =~ /^[a-z]|^([%&*+\/<>^`|~-]|\+@|-@|<<|<=>?|===?|=>|=~|>>|\[\]=?|~@)$/ then type = '.' meth = parts.pop else type = nil meth = nil end elsif parts.length == 2 or parts.last =~ /::|#|\./ then type = parts.pop meth = nil elsif parts[1] == ':' then klass = parts.shift type = parts.shift meth = parts.join elsif parts[-2] != '::' or parts.last !~ /^[A-Z]/ then meth = parts.pop type = parts.pop end klass ||= parts.join [klass, type, meth] end ## # Looks up and displays ri data according to the options given. def run if @list_doc_dirs then puts @doc_dirs elsif @list then list_known_classes @names elsif @server then start_server elsif @interactive or @names.empty? then interactive else display_names @names end rescue NotFoundError => e abort e.message end ## # Sets up a pager program to pass output through. Tries the RI_PAGER and # PAGER environment variables followed by pager, less then more. def setup_pager return if @use_stdout jruby = Object.const_defined?(:RUBY_ENGINE) && RUBY_ENGINE == 'jruby' pagers = [ENV['RI_PAGER'], ENV['PAGER'], 'pager', 'less', 'more'] pagers.compact.uniq.each do |pager| next unless pager pager_cmd = pager.split.first next unless in_path? pager_cmd if jruby then case io = find_pager_jruby(pager) when nil then break when false then next else io end else io = IO.popen(pager, 'w') rescue next end next if $? and $?.pid == io.pid and $?.exited? # pager didn't work @paging = true return io end @use_stdout = true nil end ## # Starts a WEBrick server for ri. def start_server require 'webrick' server = WEBrick::HTTPServer.new :Port => @server server.mount '/', RDoc::Servlet trap 'INT' do server.shutdown end trap 'TERM' do server.shutdown end server.start end end rdoc/text.rb000064400000017140147635155430007024 0ustar00# coding: utf-8 ## # For RDoc::Text#to_html require 'strscan' ## # For RDoc::Text#snippet begin gem 'json' rescue Gem::LoadError end require 'json' ## # Methods for manipulating comment text module RDoc::Text ## # Maps markup formats to classes that can parse them. If the format is # unknown, "rdoc" format is used. MARKUP_FORMAT = { 'markdown' => RDoc::Markdown, 'rdoc' => RDoc::Markup, 'rd' => RDoc::RD, 'tomdoc' => RDoc::TomDoc, } MARKUP_FORMAT.default = RDoc::Markup ## # Maps an encoding to a Hash of characters properly transcoded for that # encoding. # # See also encode_fallback. TO_HTML_CHARACTERS = Hash.new do |h, encoding| h[encoding] = { :close_dquote => encode_fallback('”', encoding, '"'), :close_squote => encode_fallback('’', encoding, '\''), :copyright => encode_fallback('©', encoding, '(c)'), :ellipsis => encode_fallback('…', encoding, '...'), :em_dash => encode_fallback('—', encoding, '---'), :en_dash => encode_fallback('–', encoding, '--'), :open_dquote => encode_fallback('“', encoding, '"'), :open_squote => encode_fallback('‘', encoding, '\''), :trademark => encode_fallback('®', encoding, '(r)'), } end if Object.const_defined? :Encoding ## # Transcodes +character+ to +encoding+ with a +fallback+ character. def self.encode_fallback character, encoding, fallback character.encode(encoding, :fallback => { character => fallback }, :undef => :replace, :replace => fallback) end ## # Expands tab characters in +text+ to eight spaces def expand_tabs text expanded = [] text.each_line do |line| nil while line.gsub!(/(?:\G|\r)((?:.{8})*?)([^\t\r\n]{0,7})\t/) do r = "#{$1}#{$2}#{' ' * (8 - $2.size)}" r.force_encoding text.encoding if Object.const_defined? :Encoding r end expanded << line end expanded.join end ## # Flush +text+ left based on the shortest line def flush_left text indent = 9999 text.each_line do |line| line_indent = line =~ /\S/ || 9999 indent = line_indent if indent > line_indent end empty = '' empty.force_encoding text.encoding if Object.const_defined? :Encoding text.gsub(/^ {0,#{indent}}/, empty) end ## # Convert a string in markup format into HTML. # # Requires the including class to implement #formatter def markup text parse(text).accept formatter end ## # Strips hashes, expands tabs then flushes +text+ to the left def normalize_comment text return text if text.empty? text = strip_stars text text = strip_hashes text text = expand_tabs text text = flush_left text text = strip_newlines text text end ## # Normalizes +text+ then builds a RDoc::Markup::Document from it def parse text, format = 'rdoc' return text if RDoc::Markup::Document === text return text.parse if RDoc::Comment === text text = normalize_comment text # TODO remove, should not be necessary return RDoc::Markup::Document.new if text =~ /\A\n*\z/ MARKUP_FORMAT[format].parse text end ## # The first +limit+ characters of +text+ as HTML def snippet text, limit = 100 document = parse text RDoc::Markup::ToHtmlSnippet.new(limit).convert document end ## # Strips leading # characters from +text+ def strip_hashes text return text if text =~ /^(?>\s*)[^\#]/ empty = '' empty.force_encoding text.encoding if Object.const_defined? :Encoding text.gsub(/^\s*(#+)/) { $1.tr '#', ' ' }.gsub(/^\s+$/, empty) end ## # Strips leading and trailing \n characters from +text+ def strip_newlines text text.gsub(/\A\n*(.*?)\n*\z/m) do $1 end # block preserves String encoding end ## # Strips /* */ style comments def strip_stars text return text unless text =~ %r%/\*.*\*/%m encoding = text.encoding if Object.const_defined? :Encoding text = text.gsub %r%Document-method:\s+[\w:.#=!?]+%, '' space = ' ' space.force_encoding encoding if encoding text.sub! %r%/\*+% do space * $&.length end text.sub! %r%\*+/% do space * $&.length end text.gsub! %r%^[ \t]*\*%m do space * $&.length end empty = '' empty.force_encoding encoding if encoding text.gsub(/^\s+$/, empty) end ## # Converts ampersand, dashes, ellipsis, quotes, copyright and registered # trademark symbols in +text+ to properly encoded characters. def to_html text if Object.const_defined? :Encoding then html = ''.encode text.encoding encoded = RDoc::Text::TO_HTML_CHARACTERS[text.encoding] else html = '' encoded = { :close_dquote => '”', :close_squote => '’', :copyright => '©', :ellipsis => '…', :em_dash => '—', :en_dash => '–', :open_dquote => '“', :open_squote => '‘', :trademark => '®', } end s = StringScanner.new text insquotes = false indquotes = false after_word = nil until s.eos? do case when s.scan(/<(tt|code)>.*?<\/\1>/) then # skip contents of tt html << s.matched.gsub('\\\\', '\\') when s.scan(/<(tt|code)>.*?/) then warn "mismatched <#{s[1]}> tag" # TODO signal file/line html << s.matched when s.scan(/<[^>]+\/?s*>/) then # skip HTML tags html << s.matched when s.scan(/\\(\S)/) then # unhandled suppressed crossref html << s[1] after_word = nil when s.scan(/\.\.\.(\.?)/) then html << s[1] << encoded[:ellipsis] after_word = nil when s.scan(/\(c\)/) then html << encoded[:copyright] after_word = nil when s.scan(/\(r\)/) then html << encoded[:trademark] after_word = nil when s.scan(/---/) then html << encoded[:em_dash] after_word = nil when s.scan(/--/) then html << encoded[:en_dash] after_word = nil when s.scan(/"|"/) then html << encoded[indquotes ? :close_dquote : :open_dquote] indquotes = !indquotes after_word = nil when s.scan(/``/) then # backtick double quote html << encoded[:open_dquote] after_word = nil when s.scan(/''/) then # tick double quote html << encoded[:close_dquote] after_word = nil when s.scan(/'/) then # single quote if insquotes html << encoded[:close_squote] insquotes = false elsif after_word # Mary's dog, my parents' house: do not start paired quotes html << encoded[:close_squote] else html << encoded[:open_squote] insquotes = true end after_word = nil else # advance to the next potentially significant character match = s.scan(/.+?(?=[<\\.("'`&-])/) #" if match then html << match after_word = match =~ /\w$/ else html << s.rest break end end end html end ## # Wraps +txt+ to +line_len+ def wrap(txt, line_len = 76) res = [] sp = 0 ep = txt.length while sp < ep # scan back for a space p = sp + line_len - 1 if p >= ep p = ep else while p > sp and txt[p] != ?\s p -= 1 end if p <= sp p = sp + line_len while p < ep and txt[p] != ?\s p += 1 end end end res << txt[sp...p] << "\n" sp = p sp += 1 while sp < ep and txt[sp] == ?\s end res.join.strip end end rdoc/test_case.rb000064400000006733147635155430010020 0ustar00require 'rubygems' require 'minitest/autorun' require 'minitest/benchmark' if ENV['BENCHMARK'] require 'fileutils' require 'pp' require 'tempfile' require 'tmpdir' require 'stringio' require 'rdoc' ## # RDoc::TestCase is an abstract TestCase to provide common setup and teardown # across all RDoc tests. The test case uses minitest, so all the assertions # of minitest may be used. # # The testcase provides the following: # # * A reset code-object tree # * A reset markup preprocessor (RDoc::Markup::PreProcess) # * The @RM alias of RDoc::Markup (for less typing) # * @pwd containing the current working directory # * FileUtils, pp, Tempfile, Dir.tmpdir and StringIO class RDoc::TestCase < MiniTest::Unit::TestCase ## # Abstract test-case setup def setup super @top_level = nil @have_encoding = Object.const_defined? :Encoding @RM = RDoc::Markup RDoc::Markup::PreProcess.reset @pwd = Dir.pwd @store = RDoc::Store.new @rdoc = RDoc::RDoc.new @rdoc.store = @store g = Object.new def g.class_dir() end def g.file_dir() end @rdoc.generator = g end ## # Shortcut for RDoc::Markup::BlankLine.new def blank_line @RM::BlankLine.new end ## # Shortcut for RDoc::Markup::BlockQuote.new with +contents+ def block *contents @RM::BlockQuote.new(*contents) end ## # Creates an RDoc::Comment with +text+ which was defined on +top_level+. # By default the comment has the 'rdoc' format. def comment text, top_level = @top_level RDoc::Comment.new text, top_level end ## # Shortcut for RDoc::Markup::Document.new with +contents+ def doc *contents @RM::Document.new(*contents) end ## # Shortcut for RDoc::Markup::HardBreak.new def hard_break @RM::HardBreak.new end ## # Shortcut for RDoc::Markup::Heading.new with +level+ and +text+ def head level, text @RM::Heading.new level, text end ## # Shortcut for RDoc::Markup::ListItem.new with +label+ and +parts+ def item label = nil, *parts @RM::ListItem.new label, *parts end ## # Shortcut for RDoc::Markup::List.new with +type+ and +items+ def list type = nil, *items @RM::List.new type, *items end ## # Shortcut for RDoc::Markup::Paragraph.new with +contents+ def para *a @RM::Paragraph.new(*a) end ## # Shortcut for RDoc::Markup::Rule.new with +weight+ def rule weight @RM::Rule.new weight end ## # Shortcut for RDoc::Markup::Raw.new with +contents+ def raw *contents @RM::Raw.new(*contents) end ## # Creates a temporary directory changes the current directory to it for the # duration of the block. # # Depends upon Dir.mktmpdir def temp_dir skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir Dir.mktmpdir do |temp_dir| Dir.chdir temp_dir do yield temp_dir end end end ## # Shortcut for RDoc::Markup::Verbatim.new with +parts+ def verb *parts @RM::Verbatim.new(*parts) end ## # run capture_io with setting $VERBOSE = true def verbose_capture_io capture_io do begin orig_verbose = $VERBOSE $VERBOSE = true yield ensure $VERBOSE = orig_verbose end end end end # This hack allows autoload to work when Dir.pwd is changed for Ruby 1.8 since # -I paths are not expanded. $LOAD_PATH.each do |load_path| break if load_path[0] == ?/ load_path.replace File.expand_path load_path end if RUBY_VERSION < '1.9' rdoc/require.rb000064400000001647147635155430007521 0ustar00## # A file loaded by \#require class RDoc::Require < RDoc::CodeObject ## # Name of the required file attr_accessor :name ## # Creates a new Require that loads +name+ with +comment+ def initialize(name, comment) super() @name = name.gsub(/'|"/, "") #' @top_level = nil self.comment = comment end def inspect # :nodoc: "#<%s:0x%x require '%s' in %s>" % [ self.class, object_id, @name, parent_file_name, ] end def to_s # :nodoc: "require #{name} in: #{parent}" end ## # The RDoc::TopLevel corresponding to this require, or +nil+ if not found. def top_level @top_level ||= begin tl = RDoc::TopLevel.all_files_hash[name + '.rb'] if tl.nil? and RDoc::TopLevel.all_files.first.full_name =~ %r(^lib/) then # second chance tl = RDoc::TopLevel.all_files_hash['lib/' + name + '.rb'] end tl end end end rdoc/top_level.rb000064400000012636147635155430010036 0ustar00## # A TopLevel context is a representation of the contents of a single file class RDoc::TopLevel < RDoc::Context MARSHAL_VERSION = 0 # :nodoc: ## # This TopLevel's File::Stat struct attr_accessor :file_stat ## # Relative name of this file attr_accessor :relative_name ## # Absolute name of this file attr_accessor :absolute_name ## # All the classes or modules that were declared in # this file. These are assigned to either +#classes_hash+ # or +#modules_hash+ once we know what they really are. attr_reader :classes_or_modules attr_accessor :diagram # :nodoc: ## # The parser that processed this file attr_accessor :parser ## # Creates a new TopLevel for the file at +absolute_name+. If documentation # is being generated outside the source dir +relative_name+ is relative to # the source directory. def initialize absolute_name, relative_name = absolute_name super() @name = nil @absolute_name = absolute_name @relative_name = relative_name @file_stat = File.stat(absolute_name) rescue nil # HACK for testing @diagram = nil @parser = nil @classes_or_modules = [] end ## # An RDoc::TopLevel is equal to another with the same relative_name def == other self.class === other and @relative_name == other.relative_name end alias eql? == ## # Adds +an_alias+ to +Object+ instead of +self+. def add_alias(an_alias) object_class.record_location self return an_alias unless @document_self object_class.add_alias an_alias end ## # Adds +constant+ to +Object+ instead of +self+. def add_constant constant object_class.record_location self return constant unless @document_self object_class.add_constant constant end ## # Adds +include+ to +Object+ instead of +self+. def add_include(include) object_class.record_location self return include unless @document_self object_class.add_include include end ## # Adds +method+ to +Object+ instead of +self+. def add_method(method) object_class.record_location self return method unless @document_self object_class.add_method method end ## # Adds class or module +mod+. Used in the building phase # by the ruby parser. def add_to_classes_or_modules mod @classes_or_modules << mod end ## # Base name of this file def base_name File.basename @relative_name end alias name base_name ## # Only a TopLevel that contains text file) will be displayed. See also # RDoc::CodeObject#display? def display? text? and super end ## # See RDoc::TopLevel::find_class_or_module #-- # TODO Why do we search through all classes/modules found, not just the # ones of this instance? def find_class_or_module name @store.find_class_or_module name end ## # Finds a class or module named +symbol+ def find_local_symbol(symbol) find_class_or_module(symbol) || super end ## # Finds a module or class with +name+ def find_module_named(name) find_class_or_module(name) end ## # Returns the relative name of this file def full_name @relative_name end ## # An RDoc::TopLevel has the same hash as another with the same # relative_name def hash @relative_name.hash end ## # URL for this with a +prefix+ def http_url(prefix) path = [prefix, @relative_name.tr('.', '_')] File.join(*path.compact) + '.html' end def inspect # :nodoc: "#<%s:0x%x %p modules: %p classes: %p>" % [ self.class, object_id, base_name, @modules.map { |n,m| m }, @classes.map { |n,c| c } ] end ## # Time this file was last modified, if known def last_modified @file_stat ? file_stat.mtime : nil end ## # Dumps this TopLevel for use by ri. See also #marshal_load def marshal_dump [ MARSHAL_VERSION, @relative_name, @parser, parse(@comment), ] end ## # Loads this TopLevel from +array+. def marshal_load array # :nodoc: initialize array[1] @parser = array[2] @comment = array[3] @file_stat = nil end ## # Returns the NormalClass "Object", creating it if not found. # # Records +self+ as a location in "Object". def object_class @object_class ||= begin oc = @store.find_class_named('Object') || add_class(RDoc::NormalClass, 'Object') oc.record_location self oc end end ## # Base name of this file without the extension def page_name basename = File.basename @relative_name basename =~ /\.(rb|rdoc|txt|md)$/i $` || basename end ## # Path to this file for use with HTML generator output. def path http_url @store.rdoc.generator.file_dir end def pretty_print q # :nodoc: q.group 2, "[#{self.class}: ", "]" do q.text "base name: #{base_name.inspect}" q.breakable items = @modules.map { |n,m| m } items.concat @modules.map { |n,c| c } q.seplist items do |mod| q.pp mod end end end ## # Search record used by RDoc::Generator::JsonIndex def search_record return unless @parser < RDoc::Parser::Text [ page_name, '', page_name, '', path, '', snippet(@comment), ] end ## # Is this TopLevel from a text file instead of a source code file? def text? @parser and @parser.ancestors.include? RDoc::Parser::Text end def to_s # :nodoc: "file #{full_name}" end end rdoc/known_classes.rb000064400000005122147635155430010706 0ustar00module RDoc ## # Ruby's built-in classes, modules and exceptions KNOWN_CLASSES = { "rb_cArray" => "Array", "rb_cBasicObject" => "BasicObject", "rb_cBignum" => "Bignum", "rb_cClass" => "Class", "rb_cData" => "Data", "rb_cDir" => "Dir", "rb_cEncoding" => "Encoding", "rb_cFalseClass" => "FalseClass", "rb_cFile" => "File", "rb_cFixnum" => "Fixnum", "rb_cFloat" => "Float", "rb_cHash" => "Hash", "rb_cIO" => "IO", "rb_cInteger" => "Integer", "rb_cModule" => "Module", "rb_cNilClass" => "NilClass", "rb_cNumeric" => "Numeric", "rb_cObject" => "Object", "rb_cProc" => "Proc", "rb_cRange" => "Range", "rb_cRegexp" => "Regexp", "rb_cRubyVM" => "RubyVM", "rb_cSocket" => "Socket", "rb_cString" => "String", "rb_cStruct" => "Struct", "rb_cSymbol" => "Symbol", "rb_cThread" => "Thread", "rb_cTime" => "Time", "rb_cTrueClass" => "TrueClass", "rb_eArgError" => "ArgError", "rb_eEOFError" => "EOFError", "rb_eException" => "Exception", "rb_eFatal" => "fatal", "rb_eFloatDomainError" => "FloatDomainError", "rb_eIOError" => "IOError", "rb_eIndexError" => "IndexError", "rb_eInterrupt" => "Interrupt", "rb_eLoadError" => "LoadError", "rb_eNameError" => "NameError", "rb_eNoMemError" => "NoMemError", "rb_eNotImpError" => "NotImpError", "rb_eRangeError" => "RangeError", "rb_eRuntimeError" => "RuntimeError", "rb_eScriptError" => "ScriptError", "rb_eSecurityError" => "SecurityError", "rb_eSignal" => "SignalException", "rb_eStandardError" => "StandardError", "rb_eSyntaxError" => "SyntaxError", "rb_eSystemCallError" => "SystemCallError", "rb_eSystemExit" => "SystemExit", "rb_eTypeError" => "TypeError", "rb_eZeroDivError" => "ZeroDivError", "rb_mComparable" => "Comparable", "rb_mDL" => "DL", "rb_mEnumerable" => "Enumerable", "rb_mErrno" => "Errno", "rb_mFileTest" => "FileTest", "rb_mGC" => "GC", "rb_mKernel" => "Kernel", "rb_mMath" => "Math", "rb_mProcess" => "Process" } end rdoc/code_objects.rb000064400000000171147635155430010457 0ustar00# This file was used to load all the RDoc::CodeObject subclasses at once. Now # autoload handles this. require 'rdoc' rdoc/attr.rb000064400000007353147635155430007017 0ustar00## # An attribute created by \#attr, \#attr_reader, \#attr_writer or # \#attr_accessor class RDoc::Attr < RDoc::MethodAttr ## # 3:: # RDoc 4 # Added parent name and class # Added section title MARSHAL_VERSION = 3 # :nodoc: ## # Is the attribute readable ('R'), writable ('W') or both ('RW')? attr_accessor :rw ## # Creates a new Attr with body +text+, +name+, read/write status +rw+ and # +comment+. +singleton+ marks this as a class attribute. def initialize(text, name, rw, comment, singleton = false) super text, name @rw = rw @singleton = singleton self.comment = comment end ## # Attributes are equal when their names, singleton and rw are identical def == other self.class == other.class and self.name == other.name and self.rw == other.rw and self.singleton == other.singleton end ## # Add +an_alias+ as an attribute in +context+. def add_alias(an_alias, context) new_attr = self.class.new(self.text, an_alias.new_name, self.rw, self.comment, self.singleton) new_attr.record_location an_alias.file new_attr.visibility = self.visibility new_attr.is_alias_for = self @aliases << new_attr context.add_attribute new_attr new_attr end ## # The #aref prefix for attributes def aref_prefix 'attribute' end ## # Attributes never call super. See RDoc::AnyMethod#calls_super # # An RDoc::Attr can show up in the method list in some situations (see # Gem::ConfigFile) def calls_super # :nodoc: false end ## # Returns attr_reader, attr_writer or attr_accessor as appropriate. def definition case @rw when 'RW' then 'attr_accessor' when 'R' then 'attr_reader' when 'W' then 'attr_writer' end end def inspect # :nodoc: alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil visibility = self.visibility visibility = "forced #{visibility}" if force_documentation "#<%s:0x%x %s %s (%s)%s>" % [ self.class, object_id, full_name, rw, visibility, alias_for, ] end ## # Dumps this Attr for use by ri. See also #marshal_load def marshal_dump [ MARSHAL_VERSION, @name, full_name, @rw, @visibility, parse(@comment), singleton, @file.relative_name, @parent.full_name, @parent.class, @section.title ] end ## # Loads this Attr from +array+. For a loaded Attr the following # methods will return cached values: # # * #full_name # * #parent_name def marshal_load array initialize_visibility @aliases = [] @parent = nil @parent_name = nil @parent_class = nil @section = nil @file = nil version = array[0] @name = array[1] @full_name = array[2] @rw = array[3] @visibility = array[4] @comment = array[5] @singleton = array[6] || false # MARSHAL_VERSION == 0 # 7 handled below @parent_name = array[8] @parent_class = array[9] @section_title = array[10] @file = RDoc::TopLevel.new array[7] if version > 1 @parent_name ||= @full_name.split('#', 2).first end def pretty_print q # :nodoc: q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do unless comment.empty? then q.breakable q.text "comment:" q.breakable q.pp @comment end end end def to_s # :nodoc: "#{definition} #{name} in: #{parent}" end ## # Attributes do not have token streams. # # An RDoc::Attr can show up in the method list in some situations (see # Gem::ConfigFile) def token_stream # :nodoc: end end rdoc/context.rb000064400000070410147635155430007523 0ustar00require 'cgi' ## # A Context is something that can hold modules, classes, methods, attributes, # aliases, requires, and includes. Classes, modules, and files are all # Contexts. class RDoc::Context < RDoc::CodeObject include Comparable ## # Types of methods TYPES = %w[class instance] ## # If a context has these titles it will be sorted in this order. TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc: TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc: ## # Class/module aliases attr_reader :aliases ## # All attr* methods attr_reader :attributes ## # Block params to be used in the next MethodAttr parsed under this context attr_accessor :block_params ## # Constants defined attr_reader :constants ## # Sets the current documentation section of documentation attr_writer :current_section ## # Files this context is found in attr_reader :in_files ## # Modules this context includes attr_reader :includes ## # Modules this context is extended with attr_reader :extends ## # Methods defined in this context attr_reader :method_list ## # Name of this class excluding namespace. See also full_name attr_reader :name ## # Files this context requires attr_reader :requires ## # Use this section for the next method, attribute or constant added. attr_accessor :temporary_section ## # Hash old_name => [aliases], for aliases # that haven't (yet) been resolved to a method/attribute. # (Not to be confused with the aliases of the context.) attr_accessor :unmatched_alias_lists ## # Aliases that could not be resolved. attr_reader :external_aliases ## # Current visibility of this context attr_accessor :visibility ## # Hash of registered methods. Attributes are also registered here, # twice if they are RW. attr_reader :methods_hash ## # Params to be used in the next MethodAttr parsed under this context attr_accessor :params ## # Hash of registered constants. attr_reader :constants_hash ## # Creates an unnamed empty context with public current visibility def initialize super @in_files = [] @name ||= "unknown" @parent = nil @visibility = :public @current_section = Section.new self, nil, nil @sections = { nil => @current_section } @temporary_section = nil @classes = {} @modules = {} initialize_methods_etc end ## # Sets the defaults for methods and so-forth def initialize_methods_etc @method_list = [] @attributes = [] @aliases = [] @requires = [] @includes = [] @extends = [] @constants = [] @external_aliases = [] # This Hash maps a method name to a list of unmatched aliases (aliases of # a method not yet encountered). @unmatched_alias_lists = {} @methods_hash = {} @constants_hash = {} @params = nil @store ||= nil end ## # Contexts are sorted by full_name def <=>(other) full_name <=> other.full_name end ## # Adds +an_alias+ that is automatically resolved def add_alias an_alias return an_alias unless @document_self method_attr = find_method(an_alias.old_name, an_alias.singleton) || find_attribute(an_alias.old_name, an_alias.singleton) if method_attr then method_attr.add_alias an_alias, self else add_to @external_aliases, an_alias unmatched_alias_list = @unmatched_alias_lists[an_alias.pretty_old_name] ||= [] unmatched_alias_list.push an_alias end an_alias end ## # Adds +attribute+ if not already there. If it is (as method(s) or attribute), # updates the comment if it was empty. # # The attribute is registered only if it defines a new method. # For instance, attr_reader :foo will not be registered # if method +foo+ exists, but attr_accessor :foo will be registered # if method +foo+ exists, but foo= does not. def add_attribute attribute return attribute unless @document_self # mainly to check for redefinition of an attribute as a method # TODO find a policy for 'attr_reader :foo' + 'def foo=()' register = false key = nil if attribute.rw.index 'R' then key = attribute.pretty_name known = @methods_hash[key] if known then known.comment = attribute.comment if known.comment.empty? elsif registered = @methods_hash[attribute.pretty_name << '='] and RDoc::Attr === registered then registered.rw = 'RW' else @methods_hash[key] = attribute register = true end end if attribute.rw.index 'W' then key = attribute.pretty_name << '=' known = @methods_hash[key] if known then known.comment = attribute.comment if known.comment.empty? elsif registered = @methods_hash[attribute.pretty_name] and RDoc::Attr === registered then registered.rw = 'RW' else @methods_hash[key] = attribute register = true end end if register then attribute.visibility = @visibility add_to @attributes, attribute resolve_aliases attribute end attribute end ## # Adds a class named +given_name+ with +superclass+. # # Both +given_name+ and +superclass+ may contain '::', and are # interpreted relative to the +self+ context. This allows handling correctly # examples like these: # class RDoc::Gauntlet < Gauntlet # module Mod # class Object # implies < ::Object # class SubObject < Object # this is _not_ ::Object # # Given class Container::Item RDoc assumes +Container+ is a module # unless it later sees class Container. +add_class+ automatically # upgrades +given_name+ to a class in this case. def add_class class_type, given_name, superclass = '::Object' # superclass +nil+ is passed by the C parser in the following cases: # - registering Object in 1.8 (correct) # - registering BasicObject in 1.9 (correct) # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c) # # If we later find a superclass for a registered class with a nil # superclass, we must honor it. # find the name & enclosing context if given_name =~ /^:+(\w+)$/ then full_name = $1 enclosing = top_level name = full_name.split(/:+/).last else full_name = child_name given_name if full_name =~ /^(.+)::(\w+)$/ then name = $2 ename = $1 enclosing = @store.classes_hash[ename] || @store.modules_hash[ename] # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming) unless enclosing then # try the given name at top level (will work for the above example) enclosing = @store.classes_hash[given_name] || @store.modules_hash[given_name] return enclosing if enclosing # not found: create the parent(s) names = ename.split('::') enclosing = self names.each do |n| enclosing = enclosing.classes_hash[n] || enclosing.modules_hash[n] || enclosing.add_module(RDoc::NormalModule, n) end end else name = full_name enclosing = self end end # fix up superclass superclass = nil if full_name == 'BasicObject' superclass = nil if full_name == 'Object' and defined?(::BasicObject) superclass = '::BasicObject' if defined?(::BasicObject) and full_name == 'Object' # find the superclass full name if superclass then if superclass =~ /^:+/ then superclass = $' #' else if superclass =~ /^(\w+):+(.+)$/ then suffix = $2 mod = find_module_named($1) superclass = mod.full_name + '::' + suffix if mod else mod = find_module_named(superclass) superclass = mod.full_name if mod end end # did we believe it was a module? mod = @store.modules_hash.delete superclass upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod # e.g., Object < Object superclass = nil if superclass == full_name end klass = @store.classes_hash[full_name] if klass then # if TopLevel, it may not be registered in the classes: enclosing.classes_hash[name] = klass # update the superclass if needed if superclass then existing = klass.superclass existing = existing.full_name unless existing.is_a?(String) if existing if existing.nil? || (existing == 'Object' && superclass != 'Object') then klass.superclass = superclass end end else # this is a new class mod = @store.modules_hash.delete full_name if mod then klass = upgrade_to_class mod, RDoc::NormalClass, enclosing klass.superclass = superclass unless superclass.nil? else klass = class_type.new name, superclass enclosing.add_class_or_module(klass, enclosing.classes_hash, @store.classes_hash) end end klass.parent = self klass end ## # Adds the class or module +mod+ to the modules or # classes Hash +self_hash+, and to +all_hash+ (either # TopLevel::modules_hash or TopLevel::classes_hash), # unless #done_documenting is +true+. Sets the #parent of +mod+ # to +self+, and its #section to #current_section. Returns +mod+. def add_class_or_module mod, self_hash, all_hash mod.section = current_section # TODO declaring context? something is # wrong here... mod.parent = self mod.store = @store unless @done_documenting then self_hash[mod.name] = mod # this must be done AFTER adding mod to its parent, so that the full # name is correct: all_hash[mod.full_name] = mod end mod end ## # Adds +constant+ if not already there. If it is, updates the comment, # value and/or is_alias_for of the known constant if they were empty/nil. def add_constant constant return constant unless @document_self # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code) # (this is a #ifdef: should be handled by the C parser) known = @constants_hash[constant.name] if known then known.comment = constant.comment if known.comment.empty? known.value = constant.value if known.value.nil? or known.value.strip.empty? known.is_alias_for ||= constant.is_alias_for else @constants_hash[constant.name] = constant add_to @constants, constant end constant end ## # Adds included module +include+ which should be an RDoc::Include def add_include include add_to @includes, include include end ## # Adds extension module +ext+ which should be an RDoc::Extend def add_extend ext add_to @extends, ext ext end ## # Adds +method+ if not already there. If it is (as method or attribute), # updates the comment if it was empty. def add_method method return method unless @document_self # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code) key = method.pretty_name known = @methods_hash[key] if known then if @store then # otherwise we are loading known.comment = method.comment if known.comment.empty? previously = ", previously in #{known.file}" unless method.file == known.file @store.rdoc.options.warn \ "Duplicate method #{known.full_name} in #{method.file}#{previously}" end else @methods_hash[key] = method method.visibility = @visibility add_to @method_list, method resolve_aliases method end method end ## # Adds a module named +name+. If RDoc already knows +name+ is a class then # that class is returned instead. See also #add_class. def add_module(class_type, name) mod = @classes[name] || @modules[name] return mod if mod full_name = child_name name mod = @store.modules_hash[full_name] || class_type.new(name) add_class_or_module mod, @modules, @store.modules_hash end ## # Adds an alias from +from+ (a class or module) to +name+ which was defined # in +file+. def add_module_alias from, name, file return from if @done_documenting to_name = child_name name # if we already know this name, don't register an alias: # see the metaprogramming in lib/active_support/basic_object.rb, # where we already know BasicObject is a class when we find # BasicObject = BlankSlate return from if @store.find_class_or_module to_name to = from.dup to.name = name to.full_name = nil if to.module? then @store.modules_hash[to_name] = to @modules[name] = to else @store.classes_hash[to_name] = to @classes[name] = to end # Registers a constant for this alias. The constant value and comment # will be updated later, when the Ruby parser adds the constant const = RDoc::Constant.new name, nil, to.comment const.record_location file const.is_alias_for = from add_constant const to end ## # Adds +require+ to this context's top level def add_require(require) return require unless @document_self if RDoc::TopLevel === self then add_to @requires, require else parent.add_require require end end ## # Returns a section with +title+, creating it if it doesn't already exist. # +comment+ will be appended to the section's comment. # # A section with a +title+ of +nil+ will return the default section. # # See also RDoc::Context::Section def add_section title, comment = nil if section = @sections[title] then section.add_comment comment if comment else section = Section.new self, title, comment @sections[title] = section end section end ## # Adds +thing+ to the collection +array+ def add_to array, thing array << thing if @document_self thing.parent = self thing.store = @store if @store thing.section = current_section end ## # Is there any content? # # This means any of: comment, aliases, methods, attributes, external # aliases, require, constant. # # Includes and extends are also checked unless includes == false. def any_content(includes = true) @any_content ||= !( @comment.empty? && @method_list.empty? && @attributes.empty? && @aliases.empty? && @external_aliases.empty? && @requires.empty? && @constants.empty? ) @any_content || (includes && !(@includes + @extends).empty? ) end ## # Creates the full name for a child with +name+ def child_name name if name =~ /^:+/ $' #' elsif RDoc::TopLevel === self then name else "#{self.full_name}::#{name}" end end ## # Class attributes def class_attributes @class_attributes ||= attributes.select { |a| a.singleton } end ## # Class methods def class_method_list @class_method_list ||= method_list.select { |a| a.singleton } end ## # Array of classes in this context def classes @classes.values end ## # All classes and modules in this namespace def classes_and_modules classes + modules end ## # Hash of classes keyed by class name def classes_hash @classes end ## # The current documentation section that new items will be added to. If # temporary_section is available it will be used. def current_section if section = @temporary_section then @temporary_section = nil else section = @current_section end section end ## # Is part of this thing was defined in +file+? def defined_in?(file) @in_files.include?(file) end def display(method_attr) # :nodoc: if method_attr.is_a? RDoc::Attr "#{method_attr.definition} #{method_attr.pretty_name}" else "method #{method_attr.pretty_name}" end end ## # Iterator for ancestors for duck-typing. Does nothing. See # RDoc::ClassModule#each_ancestor. # # This method exists to make it easy to work with Context subclasses that # aren't part of RDoc. def each_ancestor # :nodoc: end ## # Iterator for attributes def each_attribute # :yields: attribute @attributes.each { |a| yield a } end ## # Iterator for classes and modules def each_classmodule(&block) # :yields: module classes_and_modules.sort.each(&block) end ## # Iterator for constants def each_constant # :yields: constant @constants.each {|c| yield c} end ## # Iterator for included modules def each_include # :yields: include @includes.each do |i| yield i end end ## # Iterator for extension modules def each_extend # :yields: extend @extends.each do |e| yield e end end ## # Iterator for methods def each_method # :yields: method return enum_for __method__ unless block_given? @method_list.sort.each { |m| yield m } end ## # Iterator for each section's contents sorted by title. The +section+, the # section's +constants+ and the sections +attributes+ are yielded. The # +constants+ and +attributes+ collections are sorted. # # To retrieve methods in a section use #methods_by_type with the optional # +section+ parameter. # # NOTE: Do not edit collections yielded by this method def each_section # :yields: section, constants, attributes return enum_for __method__ unless block_given? constants = @constants.group_by do |constant| constant.section end attributes = @attributes.group_by do |attribute| attribute.section end constants.default = [] attributes.default = [] sort_sections.each do |section| yield section, constants[section].sort, attributes[section].sort end end ## # Finds an attribute +name+ with singleton value +singleton+. def find_attribute(name, singleton) name = $1 if name =~ /^(.*)=$/ @attributes.find { |a| a.name == name && a.singleton == singleton } end ## # Finds an attribute with +name+ in this context def find_attribute_named(name) case name when /\A#/ then find_attribute name[1..-1], false when /\A::/ then find_attribute name[2..-1], true else @attributes.find { |a| a.name == name } end end ## # Finds a class method with +name+ in this context def find_class_method_named(name) @method_list.find { |meth| meth.singleton && meth.name == name } end ## # Finds a constant with +name+ in this context def find_constant_named(name) @constants.find {|m| m.name == name} end ## # Find a module at a higher scope def find_enclosing_module_named(name) parent && parent.find_module_named(name) end ## # Finds an external alias +name+ with singleton value +singleton+. def find_external_alias(name, singleton) @external_aliases.find { |m| m.name == name && m.singleton == singleton } end ## # Finds an external alias with +name+ in this context def find_external_alias_named(name) case name when /\A#/ then find_external_alias name[1..-1], false when /\A::/ then find_external_alias name[2..-1], true else @external_aliases.find { |a| a.name == name } end end ## # Finds a file with +name+ in this context def find_file_named name @store.find_file_named name end ## # Finds an instance method with +name+ in this context def find_instance_method_named(name) @method_list.find { |meth| !meth.singleton && meth.name == name } end ## # Finds a method, constant, attribute, external alias, module or file # named +symbol+ in this context. def find_local_symbol(symbol) find_method_named(symbol) or find_constant_named(symbol) or find_attribute_named(symbol) or find_external_alias_named(symbol) or find_module_named(symbol) or find_file_named(symbol) end ## # Finds a method named +name+ with singleton value +singleton+. def find_method(name, singleton) @method_list.find { |m| m.name == name && m.singleton == singleton } end ## # Finds a instance or module method with +name+ in this context def find_method_named(name) case name when /\A#/ then find_method name[1..-1], false when /\A::/ then find_method name[2..-1], true else @method_list.find { |meth| meth.name == name } end end ## # Find a module with +name+ using ruby's scoping rules def find_module_named(name) res = @modules[name] || @classes[name] return res if res return self if self.name == name find_enclosing_module_named name end ## # Look up +symbol+, first as a module, then as a local symbol. def find_symbol(symbol) find_symbol_module(symbol) || find_local_symbol(symbol) end ## # Look up a module named +symbol+. def find_symbol_module(symbol) result = nil # look for a class or module 'symbol' case symbol when /^::/ then result = @store.find_class_or_module symbol when /^(\w+):+(.+)$/ suffix = $2 top = $1 searched = self while searched do mod = searched.find_module_named(top) break unless mod result = @store.find_class_or_module "#{mod.full_name}::#{suffix}" break if result || searched.is_a?(RDoc::TopLevel) searched = searched.parent end else searched = self while searched do result = searched.find_module_named(symbol) break if result || searched.is_a?(RDoc::TopLevel) searched = searched.parent end end result end ## # The full name for this context. This method is overridden by subclasses. def full_name '(unknown)' end ## # Does this context and its methods and constants all have documentation? # # (Yes, fully documented doesn't mean everything.) def fully_documented? documented? and attributes.all? { |a| a.documented? } and method_list.all? { |m| m.documented? } and constants.all? { |c| c.documented? } end ## # URL for this with a +prefix+ def http_url(prefix) path = name_for_path path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<'class' or # 'instance') and visibility (+:public+, +:protected+, +:private+). # # If +section+ is provided only methods in that RDoc::Context::Section will # be returned. def methods_by_type section = nil methods = {} TYPES.each do |type| visibilities = {} RDoc::VISIBILITIES.each do |vis| visibilities[vis] = [] end methods[type] = visibilities end each_method do |method| next if section and not method.section == section methods[method.type][method.visibility] << method end methods end ## # Yields AnyMethod and Attr entries matching the list of names in +methods+. def methods_matching(methods, singleton = false, &block) (@method_list + @attributes).each do |m| yield m if methods.include?(m.name) and m.singleton == singleton end each_ancestor do |parent| parent.methods_matching(methods, singleton, &block) end end ## # Array of modules in this context def modules @modules.values end ## # Hash of modules keyed by module name def modules_hash @modules end ## # Name to use to generate the url. # #full_name by default. def name_for_path full_name end ## # Changes the visibility for new methods to +visibility+ def ongoing_visibility=(visibility) @visibility = visibility end ## # Record +top_level+ as a file +self+ is in. def record_location(top_level) @in_files << top_level unless @in_files.include?(top_level) end ## # Should we remove this context from the documentation? # # The answer is yes if: # * #received_nodoc is +true+ # * #any_content is +false+ (not counting includes) # * All #includes are modules (not a string), and their module has # #remove_from_documentation? == true # * All classes and modules have #remove_from_documentation? == true def remove_from_documentation? @remove_from_documentation ||= @received_nodoc && !any_content(false) && @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } && classes_and_modules.all? { |cm| cm.remove_from_documentation? } end ## # Removes methods and attributes with a visibility less than +min_visibility+. #-- # TODO mark the visibility of attributes in the template (if not public?) def remove_invisible(min_visibility) return if min_visibility == :private remove_invisible_in @method_list, min_visibility remove_invisible_in @attributes, min_visibility end ## # Only called when min_visibility == :public or :private def remove_invisible_in array, min_visibility # :nodoc: if min_visibility == :public then array.reject! { |e| e.visibility != :public and not e.force_documentation } else array.reject! { |e| e.visibility == :private and not e.force_documentation } end end ## # Tries to resolve unmatched aliases when a method or attribute has just # been added. def resolve_aliases added # resolve any pending unmatched aliases key = added.pretty_name unmatched_alias_list = @unmatched_alias_lists[key] return unless unmatched_alias_list unmatched_alias_list.each do |unmatched_alias| added.add_alias unmatched_alias, self @external_aliases.delete unmatched_alias end @unmatched_alias_lists.delete key end ## # Returns RDoc::Context::Section objects referenced in this context for use # in a table of contents. def section_contents used_sections = {} each_method do |method| next unless method.display? used_sections[method.section] = true end # order found sections sections = sort_sections.select do |section| used_sections[section] end # only the default section is used return [] if sections.length == 1 and not sections.first.title sections end ## # Sections in this context def sections @sections.values end def sections_hash # :nodoc: @sections end ## # Sets the current section to a section with +title+. See also #add_section def set_current_section title, comment @current_section = add_section title, comment end ## # Given an array +methods+ of method names, set the visibility of each to # +visibility+ def set_visibility_for(methods, visibility, singleton = false) methods_matching methods, singleton do |m| m.visibility = visibility end end ## # Sorts sections alphabetically (default) or in TomDoc fashion (none, # Public, Internal, Deprecated) def sort_sections titles = @sections.map { |title, _| title } if titles.length > 1 and TOMDOC_TITLES_SORT == (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then @sections.values_at(*TOMDOC_TITLES).compact else @sections.sort_by { |title, _| title.to_s }.map { |_, section| section } end end def to_s # :nodoc: "#{self.class.name} #{self.full_name}" end ## # Return the TopLevel that owns us #-- # FIXME we can be 'owned' by several TopLevel (see #record_location & # #in_files) def top_level return @top_level if defined? @top_level @top_level = self @top_level = @top_level.parent until RDoc::TopLevel === @top_level @top_level end ## # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+ def upgrade_to_class mod, class_type, enclosing enclosing.modules_hash.delete mod.name klass = RDoc::ClassModule.from_module class_type, mod klass.store = @store # if it was there, then we keep it even if done_documenting @store.classes_hash[mod.full_name] = klass enclosing.classes_hash[mod.name] = klass klass end autoload :Section, 'rdoc/context/section' end rdoc/normal_class.rb000064400000004074147635155430010517 0ustar00## # A normal class, neither singleton nor anonymous class RDoc::NormalClass < RDoc::ClassModule ## # The ancestors of this class including modules. Unlike Module#ancestors, # this class is not included in the result. The result will contain both # RDoc::ClassModules and Strings. def ancestors if String === superclass then super << superclass elsif superclass then ancestors = super ancestors << superclass ancestors.concat superclass.ancestors else super end end ## # The definition of this class, class MyClassName def definition "class #{full_name}" end def direct_ancestors superclass ? super + [superclass] : super end def inspect # :nodoc: superclass = @superclass ? " < #{@superclass}" : nil "<%s:0x%x class %s%s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [ self.class, object_id, full_name, superclass, @includes, @extends, @attributes, @method_list, @aliases ] end def to_s # :nodoc: display = "#{self.class.name} #{self.full_name}" if superclass display << ' < ' << (superclass.is_a?(String) ? superclass : superclass.full_name) end display << ' -> ' << is_alias_for.to_s if is_alias_for display end def pretty_print q # :nodoc: superclass = @superclass ? " < #{@superclass}" : nil q.group 2, "[class #{full_name}#{superclass} ", "]" do q.breakable q.text "includes:" q.breakable q.seplist @includes do |inc| q.pp inc end q.breakable q.text "constants:" q.breakable q.seplist @constants do |const| q.pp const end q.breakable q.text "attributes:" q.breakable q.seplist @attributes do |attr| q.pp attr end q.breakable q.text "methods:" q.breakable q.seplist @method_list do |meth| q.pp meth end q.breakable q.text "aliases:" q.breakable q.seplist @aliases do |aliaz| q.pp aliaz end q.breakable q.text "comment:" q.breakable q.pp comment end end end rdoc/rd.rb000064400000007047147635155430006452 0ustar00## # RDoc::RD implements the RD format from the rdtool gem. # # To choose RD as your only default format see # RDoc::Options@Saved+Options for instructions on setting up a # .doc_options file to store your project default. # # == LICENSE # # The grammar that produces RDoc::RD::BlockParser and RDoc::RD::InlineParser # is included in RDoc under the Ruby License. # # You can find the original source for rdtool at # https://github.com/uwabami/rdtool/ # # You can use, re-distribute or change these files under Ruby's License or GPL. # # 1. You may make and give away verbatim copies of the source form of the # software without restriction, provided that you duplicate all of the # original copyright notices and associated disclaimers. # # 2. You may modify your copy of the software in any way, provided that # you do at least ONE of the following: # # a. place your modifications in the Public Domain or otherwise # make them Freely Available, such as by posting said # modifications to Usenet or an equivalent medium, or by allowing # the author to include your modifications in the software. # # b. use the modified software only within your corporation or # organization. # # c. give non-standard binaries non-standard names, with # instructions on where to get the original software distribution. # # d. make other distribution arrangements with the author. # # 3. You may distribute the software in object code or binary form, # provided that you do at least ONE of the following: # # a. distribute the binaries and library files of the software, # together with instructions (in the manual page or equivalent) # on where to get the original distribution. # # b. accompany the distribution with the machine-readable source of # the software. # # c. give non-standard binaries non-standard names, with # instructions on where to get the original software distribution. # # d. make other distribution arrangements with the author. # # 4. You may modify and include the part of the software into any other # software (possibly commercial). But some files in the distribution # are not written by the author, so that they are not under these terms. # # For the list of those files and their copying conditions, see the # file LEGAL. # # 5. The scripts and library files supplied as input to or produced as # output from the software do not automatically fall under the # copyright of the software, but belong to whomever generated them, # and may be sold commercially, and may be aggregated with this # software. # # 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE. class RDoc::RD ## # Parses +rd+ source and returns an RDoc::Markup::Document. If the # =begin or =end lines are missing they will be added. def self.parse rd rd = rd.lines.to_a if rd.find { |i| /\S/ === i } and !rd.find{|i| /^=begin\b/ === i } then rd.unshift("=begin\n").push("=end\n") end parser = RDoc::RD::BlockParser.new document = parser.parse rd # isn't this always true? document.parts.shift if RDoc::Markup::BlankLine === document.parts.first document.parts.pop if RDoc::Markup::BlankLine === document.parts.last document end autoload :BlockParser, 'rdoc/rd/block_parser' autoload :InlineParser, 'rdoc/rd/inline_parser' autoload :Inline, 'rdoc/rd/inline' end rdoc/markup.rb000064400000070472147635155430007346 0ustar00## # RDoc::Markup parses plain text documents and attempts to decompose them into # their constituent parts. Some of these parts are high-level: paragraphs, # chunks of verbatim text, list entries and the like. Other parts happen at # the character level: a piece of bold text, a word in code font. This markup # is similar in spirit to that used on WikiWiki webs, where folks create web # pages using a simple set of formatting rules. # # RDoc::Markup and other markup formats do no output formatting, this is # handled by the RDoc::Markup::Formatter subclasses. # # = Supported Formats # # Besides the RDoc::Markup format, the following formats are built in to RDoc: # # markdown:: # The markdown format as described by # http://daringfireball.net/projects/markdown/. See RDoc::Markdown for # details on the parser and supported extensions. # rd:: # The rdtool format. See RDoc::RD for details on the parser and format. # tomdoc:: # The TomDoc format as described by http://tomdoc.org/. See RDoc::TomDoc # for details on the parser and supported extensions. # # You can choose a markup format using the following methods: # # per project:: # If you build your documentation with rake use RDoc::Task#markup. # # If you build your documentation by hand run: # # rdoc --markup your_favorite_format --write-options # # and commit .rdoc_options and ship it with your packaged gem. # per file:: # At the top of the file use the :markup: directive to set the # default format for the rest of the file. # per comment:: # Use the :markup: directive at the top of a comment you want # to write in a different format. # # = RDoc::Markup # # RDoc::Markup is extensible at runtime: you can add \new markup elements to # be recognized in the documents that RDoc::Markup parses. # # RDoc::Markup is intended to be the basis for a family of tools which share # the common requirement that simple, plain-text should be rendered in a # variety of different output formats and media. It is envisaged that # RDoc::Markup could be the basis for formatting RDoc style comment blocks, # Wiki entries, and online FAQs. # # == Synopsis # # This code converts +input_string+ to HTML. The conversion takes place in # the +convert+ method, so you can use the same RDoc::Markup converter to # convert multiple input strings. # # require 'rdoc' # # h = RDoc::Markup::ToHtml.new # # puts h.convert(input_string) # # You can extend the RDoc::Markup parser to recognize new markup # sequences, and to add special processing for text that matches a # regular expression. Here we make WikiWords significant to the parser, # and also make the sequences {word} and \text... signify # strike-through text. We then subclass the HTML output class to deal # with these: # # require 'rdoc' # # class WikiHtml < RDoc::Markup::ToHtml # def handle_special_WIKIWORD(special) # "" + special.text + "" # end # end # # markup = RDoc::Markup.new # markup.add_word_pair("{", "}", :STRIKE) # markup.add_html("no", :STRIKE) # # markup.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD) # # wh = WikiHtml.new markup # wh.add_tag(:STRIKE, "", "") # # puts "#{wh.convert ARGF.read}" # # == Encoding # # Where Encoding support is available, RDoc will automatically convert all # documents to the same output encoding. The output encoding can be set via # RDoc::Options#encoding and defaults to Encoding.default_external. # # = \RDoc Markup Reference # # == Block Markup # # === Paragraphs and Verbatim # # The markup engine looks for a document's natural left margin. This is # used as the initial margin for the document. # # Consecutive lines starting at this margin are considered to be a # paragraph. Empty lines separate paragraphs. # # Any line that starts to the right of the current margin is treated # as verbatim text. This is useful for code listings: # # 3.times { puts "Ruby" } # # In verbatim text, two or more blank lines are collapsed into one, # and trailing blank lines are removed: # # This is the first line # # # This is the second non-blank line, # after 2 blank lines in the source markup. # # # There were two trailing blank lines right above this paragraph, that # have been removed. In addition, the verbatim text has been shifted # left, so the amount of indentation of verbatim text is unimportant. # # For HTML output RDoc makes a small effort to determine if a verbatim section # contains ruby source code. If so, the verbatim block will be marked up as # HTML. Triggers include "def", "class", "module", "require", the "hash # rocket"# (=>) or a block call with a parameter. # # === Headers # # A line starting with an equal sign (=) is treated as a # heading. Level one headings have one equals sign, level two headings # have two, and so on until level six, which is the maximum # (seven hyphens or more result in a level six heading). # # For example, the above header was obtained with: # # === Headers # # In HTML output headers have an id matching their name. The above example's # HTML is: # #

Headers

# # If a heading is inside a method body the id will be prefixed with the # method's id. If the above header where in the documentation for a method # such as: # # ## # # This method does fun things # # # # = Example # # # # Example of fun things goes here ... # # def do_fun_things # end # # The header's id would be: # #

Example

# # The label can be linked-to using SomeClass@Headers. See # {Links}[RDoc::Markup@Links] for further details. # # === Rules # # A line starting with three or more hyphens (at the current indent) # generates a horizontal rule. The more hyphens, the thicker the rule # (within reason, and if supported by the output device). # # In the case of HTML output, three dashes generate a 1-pixel high rule, # four dashes result in 2 pixels, and so on. The actual height is limited # to 10 pixels: # # --- # ----- # ----------------------------------------------------- # # produces: # # --- # ----- # ----------------------------------------------------- # # === Simple Lists # # If a paragraph starts with a "*", "-", "." or ".", # then it is taken to be the start of a list. The margin is increased to be # the first non-space following the list start flag. Subsequent lines # should be indented to this new margin until the list ends. For example: # # * this is a list with three paragraphs in # the first item. This is the first paragraph. # # And this is the second paragraph. # # 1. This is an indented, numbered list. # 2. This is the second item in that list # # This is the third conventional paragraph in the # first list item. # # * This is the second item in the original list # # produces: # # * this is a list with three paragraphs in # the first item. This is the first paragraph. # # And this is the second paragraph. # # 1. This is an indented, numbered list. # 2. This is the second item in that list # # This is the third conventional paragraph in the # first list item. # # * This is the second item in the original list # # === Labeled Lists # # You can also construct labeled lists, sometimes called description # or definition lists. Do this by putting the label in square brackets # and indenting the list body: # # [cat] a small furry mammal # that seems to sleep a lot # # [ant] a little insect that is known # to enjoy picnics # # produces: # # [cat] a small furry mammal # that seems to sleep a lot # # [ant] a little insect that is known # to enjoy picnics # # If you want the list bodies to line up to the left of the labels, # use two colons: # # cat:: a small furry mammal # that seems to sleep a lot # # ant:: a little insect that is known # to enjoy picnics # # produces: # # cat:: a small furry mammal # that seems to sleep a lot # # ant:: a little insect that is known # to enjoy picnics # # Notice that blank lines right after the label are ignored in labeled lists: # # [one] # # definition 1 # # [two] # # definition 2 # # produces the same output as # # [one] definition 1 # [two] definition 2 # # # === Lists and Verbatim # # If you want to introduce a verbatim section right after a list, it has to be # less indented than the list item bodies, but more indented than the list # label, letter, digit or bullet. For instance: # # * point 1 # # * point 2, first paragraph # # point 2, second paragraph # verbatim text inside point 2 # point 2, third paragraph # verbatim text outside of the list (the list is therefore closed) # regular paragraph after the list # # produces: # # * point 1 # # * point 2, first paragraph # # point 2, second paragraph # verbatim text inside point 2 # point 2, third paragraph # verbatim text outside of the list (the list is therefore closed) # regular paragraph after the list # # == Text Markup # # === Bold, Italic, Typewriter Text # # You can use markup within text (except verbatim) to change the # appearance of parts of that text. Out of the box, RDoc::Markup # supports word-based and general markup. # # Word-based markup uses flag characters around individual words: # # \*_word_\*:: displays _word_ in a *bold* font # \__word_\_:: displays _word_ in an _emphasized_ font # \+_word_\+:: displays _word_ in a +code+ font # # General markup affects text between a start delimiter and an end # delimiter. Not surprisingly, these delimiters look like HTML markup. # # \_text_:: displays _text_ in a *bold* font # \_text_:: displays _text_ in an _emphasized_ font # (alternate tag: \) # \_text_\:: displays _text_ in a +code+ font # (alternate tag: \) # # Unlike conventional Wiki markup, general markup can cross line # boundaries. You can turn off the interpretation of markup by # preceding the first character with a backslash (see Escaping # Text Markup, below). # # === Links # # Links to starting with +http:+, +https:+, +mailto:+, +ftp:+ or +www.+ # are recognized. An HTTP url that references an external image is converted # into an inline image element. # # Classes and methods will be automatically linked to their definition. For # example, RDoc::Markup will link to this documentation. By default # methods will only be automatically linked if they contain an _ (all # methods can be automatically linked through the --hyperlink-all # command line option). # # Single-word methods can be linked by using the # character for # instance methods or :: for class methods. For example, # #convert links to #convert. A class or method may be combined like # RDoc::Markup#convert. # # A heading inside the documentation can be linked by following the class # or method by an @ then the heading name. # RDoc::Markup@Links will link to this section like this: # RDoc::Markup@Links. Spaces in headings with multiple words must be escaped # with + like RDoc::Markup@Escaping+Text+Markup. # Punctuation and other special characters must be escaped like CGI.escape. # # Links can also be of the form label[url], in which case +label+ is # used in the displayed text, and +url+ is used as the target. If +label+ # contains multiple words, put it in braces: {multi word label}[url]. # The +url+ may be an +http:+-type link or a cross-reference to a class, # module or method with a label. # # Links with the rdoc-ref: scheme will link to the referenced class, # module, method, file, etc. If the referenced item is does not exist # no link will be generated and rdoc-ref: will be removed from the # resulting text. # # Links starting with rdoc-label:label_name will link to the # +label_name+. You can create a label for the current link (for # bidirectional links) by supplying a name for the current link like # rdoc-label:label-other:label-mine. # # Links starting with +link:+ refer to local files whose path is relative to # the --op directory. Use rdoc-ref: instead of # link: to link to files generated by RDoc as the link target may # be different across RDoc generators. # # Example links: # # https://github.com/rdoc/rdoc # mailto:user@example.com # {RDoc Documentation}[http://rdoc.rubyforge.org] # {RDoc Markup}[rdoc-ref:RDoc::Markup] # # === Escaping Text Markup # # Text markup can be escaped with a backslash, as in \, which was obtained # with \\. Except in verbatim sections and between \ tags, # to produce a backslash you have to double it unless it is followed by a # space, tab or newline. Otherwise, the HTML formatter will discard it, as it # is used to escape potential links: # # * The \ must be doubled if not followed by white space: \\. # * But not in \ tags: in a Regexp, \S matches non-space. # * This is a link to {ruby-lang}[www.ruby-lang.org]. # * This is not a link, however: \{ruby-lang.org}[www.ruby-lang.org]. # * This will not be linked to \RDoc::RDoc#document # # generates: # # * The \ must be doubled if not followed by white space: \\. # * But not in \ tags: in a Regexp, \S matches non-space. # * This is a link to {ruby-lang}[www.ruby-lang.org] # * This is not a link, however: \{ruby-lang.org}[www.ruby-lang.org] # * This will not be linked to \RDoc::RDoc#document # # Inside \ tags, more precisely, leading backslashes are removed only if # followed by a markup character (<*_+), a backslash, or a known link # reference (a known class or method). So in the example above, the backslash # of \S would be removed if there was a class or module named +S+ in # the current context. # # This behavior is inherited from RDoc version 1, and has been kept for # compatibility with existing RDoc documentation. # # === Conversion of characters # # HTML will convert two/three dashes to an em-dash. Other common characters are # converted as well: # # em-dash:: -- or --- # ellipsis:: ... # # single quotes:: 'text' or `text' # double quotes:: "text" or ``text'' # # copyright:: (c) # registered trademark:: (r) # # produces: # # em-dash:: -- or --- # ellipsis:: ... # # single quotes:: 'text' or `text' # double quotes:: "text" or ``text'' # # copyright:: (c) # registered trademark:: (r) # # # == Documenting Source Code # # Comment blocks can be written fairly naturally, either using # on # successive lines of the comment, or by including the comment in # a =begin/=end block. If you use the latter form, # the =begin line _must_ be flagged with an +rdoc+ tag: # # =begin rdoc # Documentation to be processed by RDoc. # # ... # =end # # RDoc stops processing comments if it finds a comment line starting # with -- right after the # character (otherwise, # it will be treated as a rule if it has three dashes or more). # This can be used to separate external from internal comments, # or to stop a comment being associated with a method, class, or module. # Commenting can be turned back on with a line that starts with ++. # # ## # # Extract the age and calculate the date-of-birth. # #-- # # FIXME: fails if the birthday falls on February 29th # #++ # # The DOB is returned as a Time object. # # def get_dob(person) # # ... # end # # Names of classes, files, and any method names containing an underscore or # preceded by a hash character are automatically linked from comment text to # their description. This linking works inside the current class or module, # and with ancestor methods (in included modules or in the superclass). # # Method parameter lists are extracted and displayed with the method # description. If a method calls +yield+, then the parameters passed to yield # will also be displayed: # # def fred # ... # yield line, address # # This will get documented as: # # fred() { |line, address| ... } # # You can override this using a comment containing ':yields: ...' immediately # after the method definition # # def fred # :yields: index, position # # ... # # yield line, address # # which will get documented as # # fred() { |index, position| ... } # # +:yields:+ is an example of a documentation directive. These appear # immediately after the start of the document element they are modifying. # # RDoc automatically cross-references words with underscores or camel-case. # To suppress cross-references, prefix the word with a \ character. To # include special characters like "\n", you'll need to use # two \ characters in normal text, but only one in \ text: # # "\\n" or "\n" # # produces: # # "\\n" or "\n" # # == Directives # # Directives are keywords surrounded by ":" characters. # # === Controlling what is documented # # [+:nodoc:+ / :nodoc: all] # This directive prevents documentation for the element from # being generated. For classes and modules, methods, aliases, # constants, and attributes directly within the affected class or # module also will be omitted. By default, though, modules and # classes within that class or module _will_ be documented. This is # turned off by adding the +all+ modifier. # # module MyModule # :nodoc: # class Input # end # end # # module OtherModule # :nodoc: all # class Output # end # end # # In the above code, only class MyModule::Input will be documented. # # The +:nodoc:+ directive, like +:enddoc:+, +:stopdoc:+ and +:startdoc:+ # presented below, is local to the current file: if you do not want to # document a module that appears in several files, specify +:nodoc:+ on each # appearance, at least once per file. # # [+:stopdoc:+ / +:startdoc:+] # Stop and start adding new documentation elements to the current container. # For example, if a class has a number of constants that you don't want to # document, put a +:stopdoc:+ before the first, and a +:startdoc:+ after the # last. If you don't specify a +:startdoc:+ by the end of the container, # disables documentation for the rest of the current file. # # [+:doc:+] # Forces a method or attribute to be documented even if it wouldn't be # otherwise. Useful if, for example, you want to include documentation of a # particular private method. # # [+:enddoc:+] # Document nothing further at the current level: directives +:startdoc:+ and # +:doc:+ that appear after this will not be honored for the current container # (file, class or module), in the current file. # # [+:notnew:+ / +:not_new:+ / +:not-new:+ ] # Only applicable to the +initialize+ instance method. Normally RDoc # assumes that the documentation and parameters for +initialize+ are # actually for the +new+ method, and so fakes out a +new+ for the class. # The +:notnew:+ directive stops this. Remember that +initialize+ is private, # so you won't see the documentation unless you use the +-a+ command line # option. # # === Method arguments # # [+:arg:+ or +:args:+ _parameters_] # Overrides the default argument handling with exactly these parameters. # # ## # # :args: a, b # # def some_method(*a) # end # # [+:yield:+ or +:yields:+ _parameters_] # Overrides the default yield discovery with these parameters. # # ## # # :yields: key, value # # def each_thing &block # @things.each(&block) # end # # [+:call-seq:+] # Lines up to the next blank line or lines with a common prefix in the # comment are treated as the method's calling sequence, overriding the # default parsing of method parameters and yield arguments. # # Multiple lines may be used. # # # :call-seq: # # ARGF.readlines(sep=$/) -> array # # ARGF.readlines(limit) -> array # # ARGF.readlines(sep, limit) -> array # # # # ARGF.to_a(sep=$/) -> array # # ARGF.to_a(limit) -> array # # ARGF.to_a(sep, limit) -> array # # # # The remaining lines are documentation ... # # === Sections # # Sections allow you to group methods in a class into sensible containers. If # you use the sections 'Public', 'Internal' and 'Deprecated' (the three # allowed method statuses from TomDoc) the sections will be displayed in that # order placing the most useful methods at the top. Otherwise, sections will # be displayed in alphabetical order. # # [+:category:+ _section_] # Adds this item to the named +section+ overriding the current section. Use # this to group methods by section in RDoc output while maintaining a # sensible ordering (like alphabetical). # # # :category: Utility Methods # # # # CGI escapes +text+ # # def convert_string text # CGI.escapeHTML text # end # # An empty category will place the item in the default category: # # # :category: # # # # This method is in the default category # # def some_method # # ... # end # # Unlike the :section: directive, :category: is not sticky. The category # only applies to the item immediately following the comment. # # Use the :section: directive to provide introductory text for a section of # documentation. # # [+:section:+ _title_] # Provides section introductory text in RDoc output. The title following # +:section:+ is used as the section name and the remainder of the comment # containing the section is used as introductory text. A section's comment # block must be separated from following comment blocks. Use an empty title # to switch to the default section. # # The :section: directive is sticky, so subsequent methods, aliases, # attributes, and classes will be contained in this section until the # section is changed. The :category: directive will override the :section: # directive. # # A :section: comment block may have one or more lines before the :section: # directive. These will be removed, and any identical lines at the end of # the block are also removed. This allows you to add visual cues to the # section. # # Example: # # # ---------------------------------------- # # :section: My Section # # This is the section that I wrote. # # See it glisten in the noon-day sun. # # ---------------------------------------- # # ## # # Comment for some_method # # def some_method # # ... # end # # === Other directives # # [+:markup:+ _type_] # Overrides the default markup type for this comment with the specified # markup type. For ruby files, if the first comment contains this directive # it is applied automatically to all comments in the file. # # Unless you are converting between markup formats you should use a # .rdoc_options file to specify the default documentation # format for your entire project. See RDoc::Options@Saved+Options for # instructions. # # At the top of a file the +:markup:+ directive applies to the entire file: # # # coding: UTF-8 # # :markup: TomDoc # # # TomDoc comment here ... # # class MyClass # # ... # # For just one comment: # # # ... # end # # # :markup: RDoc # # # # This is a comment in RDoc markup format ... # # def some_method # # ... # # See Markup@DEVELOPERS for instructions on adding a new markup format. # # [+:include:+ _filename_] # Include the contents of the named file at this point. This directive # must appear alone on one line, possibly preceded by spaces. In this # position, it can be escaped with a \ in front of the first colon. # # The file will be searched for in the directories listed by the +--include+ # option, or in the current directory by default. The contents of the file # will be shifted to have the same indentation as the ':' at the start of # the +:include:+ directive. # # [+:title:+ _text_] # Sets the title for the document. Equivalent to the --title # command line parameter. (The command line parameter overrides any :title: # directive in the source). # # [+:main:+ _name_] # Equivalent to the --main command line parameter. # #-- # Original Author:: Dave Thomas, dave@pragmaticprogrammer.com # License:: Ruby license class RDoc::Markup ## # An AttributeManager which handles inline markup. attr_reader :attribute_manager ## # Parses +str+ into an RDoc::Markup::Document. def self.parse str RDoc::Markup::Parser.parse str rescue RDoc::Markup::Parser::Error => e $stderr.puts <<-EOF While parsing markup, RDoc encountered a #{e.class}: #{e} \tfrom #{e.backtrace.join "\n\tfrom "} ---8<--- #{text} ---8<--- RDoc #{RDoc::VERSION} Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} #{RUBY_RELEASE_DATE} Please file a bug report with the above information at: https://github.com/rdoc/rdoc/issues EOF raise end ## # Take a block of text and use various heuristics to determine its # structure (paragraphs, lists, and so on). Invoke an event handler as we # identify significant chunks. def initialize attribute_manager = nil @attribute_manager = attribute_manager || RDoc::Markup::AttributeManager.new @output = nil end ## # Add to the sequences used to add formatting to an individual word (such # as *bold*). Matching entries will generate attributes that the output # formatters can recognize by their +name+. def add_word_pair(start, stop, name) @attribute_manager.add_word_pair(start, stop, name) end ## # Add to the sequences recognized as general markup. def add_html(tag, name) @attribute_manager.add_html(tag, name) end ## # Add to other inline sequences. For example, we could add WikiWords using # something like: # # parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD) # # Each wiki word will be presented to the output formatter via the # accept_special method. def add_special(pattern, name) @attribute_manager.add_special(pattern, name) end ## # We take +input+, parse it if necessary, then invoke the output +formatter+ # using a Visitor to render the result. def convert input, formatter document = case input when RDoc::Markup::Document then input else RDoc::Markup::Parser.parse input end document.accept formatter end autoload :Parser, 'rdoc/markup/parser' autoload :PreProcess, 'rdoc/markup/pre_process' # Inline markup classes autoload :AttrChanger, 'rdoc/markup/attr_changer' autoload :AttrSpan, 'rdoc/markup/attr_span' autoload :Attributes, 'rdoc/markup/attributes' autoload :AttributeManager, 'rdoc/markup/attribute_manager' autoload :Special, 'rdoc/markup/special' # RDoc::Markup AST autoload :BlankLine, 'rdoc/markup/blank_line' autoload :BlockQuote, 'rdoc/markup/block_quote' autoload :Document, 'rdoc/markup/document' autoload :HardBreak, 'rdoc/markup/hard_break' autoload :Heading, 'rdoc/markup/heading' autoload :Include, 'rdoc/markup/include' autoload :IndentedParagraph, 'rdoc/markup/indented_paragraph' autoload :List, 'rdoc/markup/list' autoload :ListItem, 'rdoc/markup/list_item' autoload :Paragraph, 'rdoc/markup/paragraph' autoload :Raw, 'rdoc/markup/raw' autoload :Rule, 'rdoc/markup/rule' autoload :Verbatim, 'rdoc/markup/verbatim' # Formatters autoload :Formatter, 'rdoc/markup/formatter' autoload :FormatterTestCase, 'rdoc/markup/formatter_test_case' autoload :TextFormatterTestCase, 'rdoc/markup/text_formatter_test_case' autoload :ToAnsi, 'rdoc/markup/to_ansi' autoload :ToBs, 'rdoc/markup/to_bs' autoload :ToHtml, 'rdoc/markup/to_html' autoload :ToHtmlCrossref, 'rdoc/markup/to_html_crossref' autoload :ToHtmlSnippet, 'rdoc/markup/to_html_snippet' autoload :ToLabel, 'rdoc/markup/to_label' autoload :ToMarkdown, 'rdoc/markup/to_markdown' autoload :ToRdoc, 'rdoc/markup/to_rdoc' autoload :ToTableOfContents, 'rdoc/markup/to_table_of_contents' autoload :ToTest, 'rdoc/markup/to_test' autoload :ToTtOnly, 'rdoc/markup/to_tt_only' end rdoc/markup/verbatim.rb000064400000002405147635155430011146 0ustar00## # A section of verbatim text class RDoc::Markup::Verbatim < RDoc::Markup::Raw ## # Format of this verbatim section attr_accessor :format def initialize *parts # :nodoc: super @format = nil end def == other # :nodoc: super and @format == other.format end ## # Calls #accept_verbatim on +visitor+ def accept visitor visitor.accept_verbatim self end ## # Collapses 3+ newlines into two newlines def normalize parts = [] newlines = 0 @parts.each do |part| case part when /^\s*\n/ then newlines += 1 parts << part if newlines == 1 else newlines = 0 parts << part end end parts.pop if parts.last =~ /\A\r?\n\z/ @parts = parts end def pretty_print q # :nodoc: self.class.name =~ /.*::(\w{1,4})/i q.group 2, "[#{$1.downcase}: ", ']' do if @format then q.text "format: #{@format}" q.breakable end q.seplist @parts do |part| q.pp part end end end ## # Is this verbatim section ruby code? def ruby? @format ||= nil # TODO for older ri data, switch the tree to marshal_dump @format == :ruby end ## # The text of the section def text @parts.join end end rdoc/markup/rule.rb000064400000000435147635155430010305 0ustar00## # A horizontal rule with a weight class RDoc::Markup::Rule < Struct.new :weight ## # Calls #accept_rule on +visitor+ def accept visitor visitor.accept_rule self end def pretty_print q # :nodoc: q.group 2, '[rule:', ']' do q.pp weight end end end rdoc/markup/paragraph.rb000064400000000717147635155430011306 0ustar00## # A Paragraph of text class RDoc::Markup::Paragraph < RDoc::Markup::Raw ## # Calls #accept_paragraph on +visitor+ def accept visitor visitor.accept_paragraph self end ## # Joins the raw paragraph text and converts inline HardBreaks to the # +hard_break+ text. def text hard_break = '' @parts.map do |part| if RDoc::Markup::HardBreak === part then hard_break else part end end.join end end rdoc/markup/hard_break.rb000064400000000640147635155430011416 0ustar00## # A hard-break in the middle of a paragraph. class RDoc::Markup::HardBreak @instance = new ## # RDoc::Markup::HardBreak is a singleton def self.new @instance end ## # Calls #accept_hard_break on +visitor+ def accept visitor visitor.accept_hard_break self end def == other # :nodoc: self.class === other end def pretty_print q # :nodoc: q.text "[break]" end end rdoc/markup/raw.rb000064400000001712147635155430010126 0ustar00## # A section of text that is added to the output document as-is class RDoc::Markup::Raw ## # The component parts of the list attr_reader :parts ## # Creates a new Raw containing +parts+ def initialize *parts @parts = [] @parts.concat parts end ## # Appends +text+ def << text @parts << text end def == other # :nodoc: self.class == other.class and @parts == other.parts end ## # Calls #accept_raw+ on +visitor+ def accept visitor visitor.accept_raw self end ## # Appends +other+'s parts def merge other @parts.concat other.parts end def pretty_print q # :nodoc: self.class.name =~ /.*::(\w{1,4})/i q.group 2, "[#{$1.downcase}: ", ']' do q.seplist @parts do |part| q.pp part end end end ## # Appends +texts+ onto this Paragraph def push *texts self.parts.concat texts end ## # The raw text def text @parts.join ' ' end end rdoc/markup/to_label.rb000064400000003422147635155430011116 0ustar00require 'cgi' ## # Creates HTML-safe labels suitable for use in id attributes. Tidylinks are # converted to their link part and cross-reference links have the suppression # marks removed (\\SomeClass is converted to SomeClass). class RDoc::Markup::ToLabel < RDoc::Markup::Formatter attr_reader :res # :nodoc: ## # Creates a new formatter that will output HTML-safe labels def initialize markup = nil super nil, markup @markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\])/, :TIDYLINK) add_tag :BOLD, '', '' add_tag :TT, '', '' add_tag :EM, '', '' @res = [] end ## # Converts +text+ to an HTML-safe label def convert text label = convert_flow @am.flow text CGI.escape label end ## # Converts the CROSSREF +special+ to plain text, removing the suppression # marker, if any def handle_special_CROSSREF special text = special.text text.sub(/^\\/, '') end ## # Converts the TIDYLINK +special+ to just the text part def handle_special_TIDYLINK special text = special.text return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/ $1 end alias accept_blank_line ignore alias accept_block_quote ignore alias accept_heading ignore alias accept_list_end ignore alias accept_list_item_end ignore alias accept_list_item_start ignore alias accept_list_start ignore alias accept_paragraph ignore alias accept_raw ignore alias accept_rule ignore alias accept_verbatim ignore alias end_accepting ignore alias handle_special_HARD_BREAK ignore alias start_accepting ignore end rdoc/markup/to_tt_only.rb000064400000004361147635155430011532 0ustar00## # Extracts sections of text enclosed in plus, tt or code. Used to discover # undocumented parameters. class RDoc::Markup::ToTtOnly < RDoc::Markup::Formatter ## # Stack of list types attr_reader :list_type ## # Output accumulator attr_reader :res ## # Creates a new tt-only formatter. def initialize markup = nil super nil, markup add_tag :TT, nil, nil end ## # Adds tts from +block_quote+ to the output def accept_block_quote block_quote tt_sections block_quote.text end ## # Pops the list type for +list+ from #list_type def accept_list_end list @list_type.pop end ## # Pushes the list type for +list+ onto #list_type def accept_list_start list @list_type << list.type end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start list_item case @list_type.last when :NOTE, :LABEL then Array(list_item.label).map do |label| tt_sections label end.flatten end end ## # Adds +paragraph+ to the output def accept_paragraph paragraph tt_sections(paragraph.text) end ## # Does nothing to +markup_item+ because it doesn't have any user-built # content def do_nothing markup_item end alias accept_blank_line do_nothing # :nodoc: alias accept_heading do_nothing # :nodoc: alias accept_list_item_end do_nothing # :nodoc: alias accept_raw do_nothing # :nodoc: alias accept_rule do_nothing # :nodoc: alias accept_verbatim do_nothing # :nodoc: ## # Extracts tt sections from +text+ def tt_sections text flow = @am.flow text.dup flow.each do |item| case item when String then @res << item if in_tt? when RDoc::Markup::AttrChanger then off_tags res, item on_tags res, item when RDoc::Markup::Special then @res << convert_special(item) if in_tt? # TODO can this happen? else raise "Unknown flow element: #{item.inspect}" end end res end ## # Returns an Array of items that were wrapped in plus, tt or code. def end_accepting @res.compact end ## # Prepares the visitor for gathering tt sections def start_accepting @res = [] @list_type = [] end end rdoc/markup/to_html.rb000064400000020160147635155430011001 0ustar00require 'cgi' ## # Outputs RDoc markup as HTML. class RDoc::Markup::ToHtml < RDoc::Markup::Formatter include RDoc::Text # :section: Utilities ## # Maps RDoc::Markup::Parser::LIST_TOKENS types to HTML tags LIST_TYPE_TO_HTML = { :BULLET => ['
    ', '
'], :LABEL => ['
', '
'], :LALPHA => ['
    ', '
'], :NOTE => ['
', '
'], :NUMBER => ['
    ', '
'], :UALPHA => ['
    ', '
'], } attr_reader :res # :nodoc: attr_reader :in_list_entry # :nodoc: attr_reader :list # :nodoc: ## # The RDoc::CodeObject HTML is being generated for. This is used to # generate namespaced URI fragments attr_accessor :code_object ## # Path to this document for relative links attr_accessor :from_path # :section: ## # Creates a new formatter that will output HTML def initialize options, markup = nil super @code_object = nil @from_path = '' @in_list_entry = nil @list = nil @th = nil @hard_break = "
\n" # external links @markup.add_special(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/, :HYPERLINK) add_special_RDOCLINK add_special_TIDYLINK init_tags end # :section: Special Handling # # These methods handle special markup added by RDoc::Markup#add_special. ## # +special+ is a
def handle_special_HARD_BREAK special '
' end ## # +special+ is a potential link. The following schemes are handled: # # mailto::: # Inserted as-is. # http::: # Links are checked to see if they reference an image. If so, that image # gets inserted using an tag. Otherwise a conventional # is used. # link::: # Reference to a local file relative to the output directory. def handle_special_HYPERLINK(special) url = special.text gen_url url, url end ## # +special+ is an rdoc-schemed link that will be converted into a hyperlink. # # For the +rdoc-ref+ scheme the named reference will be returned without # creating a link. # # For the +rdoc-label+ scheme the footnote and label prefixes are stripped # when creating a link. All other contents will be linked verbatim. def handle_special_RDOCLINK special url = special.text case url when /\Ardoc-ref:/ $' when /\Ardoc-label:/ text = $' text = case text when /\Alabel-/ then $' when /\Afootmark-/ then "^#{$'}" when /\Afoottext-/ then "*#{$'}" else text end gen_url url, text else url =~ /\Ardoc-[a-z]+:/ $' end end ## # This +special+ is a link where the label is different from the URL # label[url] or {long label}[url] def handle_special_TIDYLINK(special) text = special.text return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/ label = $1 url = $2 gen_url url, label end # :section: Visitor # # These methods implement the HTML visitor. ## # Prepares the visitor for HTML generation def start_accepting @res = [] @in_list_entry = [] @list = [] end ## # Returns the generated output def end_accepting @res.join end ## # Adds +block_quote+ to the output def accept_block_quote block_quote @res << "\n
" block_quote.parts.each do |part| part.accept self end @res << "
\n" end ## # Adds +paragraph+ to the output def accept_paragraph paragraph @res << "\n

" text = paragraph.text @hard_break @res << wrap(to_html(text)) @res << "

\n" end ## # Adds +verbatim+ to the output def accept_verbatim verbatim text = verbatim.text.rstrip @res << if verbatim.ruby? or parseable? text then begin tokens = RDoc::RubyLex.tokenize text, @options html = RDoc::TokenStream.to_html tokens "\n
#{html}
\n" rescue RDoc::RubyLex::Error "\n
#{CGI.escapeHTML text}
\n" end else "\n
#{CGI.escapeHTML text}
\n" end end ## # Adds +rule+ to the output def accept_rule(rule) size = rule.weight size = 10 if size > 10 @res << "
\n" end ## # Prepares the visitor for consuming +list+ def accept_list_start(list) @list << list.type @res << html_list_name(list.type, true) @in_list_entry.push false end ## # Finishes consumption of +list+ def accept_list_end(list) @list.pop if tag = @in_list_entry.pop @res << tag end @res << html_list_name(list.type, false) << "\n" end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start(list_item) if tag = @in_list_entry.last @res << tag end @res << list_item_start(list_item, @list.last) end ## # Finishes consumption of +list_item+ def accept_list_item_end(list_item) @in_list_entry[-1] = list_end_for(@list.last) end ## # Adds +blank_line+ to the output def accept_blank_line(blank_line) # @res << annotate("

") << "\n" end ## # Adds +heading+ to the output. The headings greater than 6 are trimmed to # level 6. def accept_heading heading level = [6, heading.level].min label = heading.aref label = [@code_object.aref, label].compact.join '-' if @code_object and @code_object.respond_to? :aref @res << "\n" @res << to_html(heading.text) unless @options.pipe then @res << "" @res << " " end @res << "\n" end ## # Adds +raw+ to the output def accept_raw raw @res << raw.parts.join("\n") end # :section: Utilities ## # CGI-escapes +text+ def convert_string(text) CGI.escapeHTML text end ## # Generate a link to +url+ with content +text+. Handles the special cases # for img: and link: described under handle_special_HYPERLINK def gen_url url, text scheme, url, id = parse_url url if %w[http https link].include?(scheme) and url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then "" else "#{text.sub(%r{^#{scheme}:/*}i, '')}" end end ## # Determines the HTML list element for +list_type+ and +open_tag+ def html_list_name(list_type, open_tag) tags = LIST_TYPE_TO_HTML[list_type] raise RDoc::Error, "Invalid list type: #{list_type.inspect}" unless tags tags[open_tag ? 0 : 1] end ## # Maps attributes to HTML tags def init_tags add_tag :BOLD, "", "" add_tag :TT, "", "" add_tag :EM, "", "" end ## # Returns the HTML tag for +list_type+, possible using a label from # +list_item+ def list_item_start(list_item, list_type) case list_type when :BULLET, :LALPHA, :NUMBER, :UALPHA then "

  • " when :LABEL, :NOTE then Array(list_item.label).map do |label| "
    #{to_html label}\n" end.join << "
    " else raise RDoc::Error, "Invalid list type: #{list_type.inspect}" end end ## # Returns the HTML end-tag for +list_type+ def list_end_for(list_type) case list_type when :BULLET, :LALPHA, :NUMBER, :UALPHA then "
  • " when :LABEL, :NOTE then "" else raise RDoc::Error, "Invalid list type: #{list_type.inspect}" end end ## # Returns true if Ripper is available it can create a sexp from +text+ def parseable? text text =~ /\b(def|class|module|require) |=>|\{\s?\||do \|/ and text !~ /<%|%>/ end ## # Converts +item+ to HTML using RDoc::Text#to_html def to_html item super convert_flow @am.flow item end end rdoc/markup/document.rb000064400000006172147635155430011160 0ustar00## # A Document containing lists, headings, paragraphs, etc. class RDoc::Markup::Document include Enumerable ## # The file this document was created from. See also # RDoc::ClassModule#add_comment attr_reader :file ## # If a heading is below the given level it will be omitted from the # table_of_contents attr_accessor :omit_headings_below ## # The parts of the Document attr_reader :parts ## # Creates a new Document with +parts+ def initialize *parts @parts = [] @parts.concat parts @file = nil @omit_headings_from_table_of_contents_below = nil end ## # Appends +part+ to the document def << part case part when RDoc::Markup::Document then unless part.empty? then parts.concat part.parts parts << RDoc::Markup::BlankLine.new end when String then raise ArgumentError, "expected RDoc::Markup::Document and friends, got String" unless part.empty? else parts << part end end def == other # :nodoc: self.class == other.class and @file == other.file and @parts == other.parts end ## # Runs this document and all its #items through +visitor+ def accept visitor visitor.start_accepting visitor.accept_document self visitor.end_accepting end ## # Concatenates the given +parts+ onto the document def concat parts self.parts.concat parts end ## # Enumerator for the parts of this document def each &block @parts.each(&block) end ## # Does this document have no parts? def empty? @parts.empty? or (@parts.length == 1 and merged? and @parts.first.empty?) end ## # The file this Document was created from. def file= location @file = case location when RDoc::TopLevel then location.relative_name else location end end ## # When this is a collection of documents (#file is not set and this document # contains only other documents as its direct children) #merge replaces # documents in this class with documents from +other+ when the file matches # and adds documents from +other+ when the files do not. # # The information in +other+ is preferred over the receiver def merge other if empty? then @parts = other.parts return self end other.parts.each do |other_part| self.parts.delete_if do |self_part| self_part.file and self_part.file == other_part.file end self.parts << other_part end self end ## # Does this Document contain other Documents? def merged? RDoc::Markup::Document === @parts.first end def pretty_print q # :nodoc: start = @file ? "[doc (#{@file}): " : '[doc: ' q.group 2, start, ']' do q.seplist @parts do |part| q.pp part end end end ## # Appends +parts+ to the document def push *parts self.parts.concat parts end ## # Returns an Array of headings in the document. # # Require 'rdoc/markup/formatter' before calling this method. def table_of_contents accept RDoc::Markup::ToTableOfContents.to_toc end end rdoc/markup/to_html_crossref.rb000064400000010256147635155430012714 0ustar00## # Subclass of the RDoc::Markup::ToHtml class that supports looking up method # names, classes, etc to create links. RDoc::CrossReference is used to # generate those links based on the current context. class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml # :stopdoc: ALL_CROSSREF_REGEXP = RDoc::CrossReference::ALL_CROSSREF_REGEXP CLASS_REGEXP_STR = RDoc::CrossReference::CLASS_REGEXP_STR CROSSREF_REGEXP = RDoc::CrossReference::CROSSREF_REGEXP METHOD_REGEXP_STR = RDoc::CrossReference::METHOD_REGEXP_STR # :startdoc: ## # RDoc::CodeObject for generating references attr_accessor :context ## # Should we show '#' characters on method references? attr_accessor :show_hash ## # Creates a new crossref resolver that generates links relative to +context+ # which lives at +from_path+ in the generated files. '#' characters on # references are removed unless +show_hash+ is true. Only method names # preceded by '#' or '::' are linked, unless +hyperlink_all+ is true. def initialize(options, from_path, context, markup = nil) raise ArgumentError, 'from_path cannot be nil' if from_path.nil? super options, markup @context = context @from_path = from_path @hyperlink_all = @options.hyperlink_all @show_hash = @options.show_hash crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP @markup.add_special crossref_re, :CROSSREF @cross_reference = RDoc::CrossReference.new @context end ## # Creates a link to the reference +name+ if the name exists. If +text+ is # given it is used as the link text, otherwise +name+ is used. def cross_reference name, text = nil lookup = name name = name[1..-1] unless @show_hash if name[0, 1] == '#' name = "#{CGI.unescape $'} at #{$1}" if name =~ /(.*[^#:])@/ text = name unless text link lookup, text end ## # We're invoked when any text matches the CROSSREF pattern. If we find the # corresponding reference, generate a link. If the name we're looking for # contains no punctuation, we look for it up the module/class chain. For # example, ToHtml is found, even without the RDoc::Markup:: prefix, # because we look for it in module Markup first. def handle_special_CROSSREF(special) name = special.text return name if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails unless @hyperlink_all then # This ensures that words entirely consisting of lowercase letters will # not have cross-references generated (to suppress lots of erroneous # cross-references to "new" in text, for instance) return name if name =~ /\A[a-z]*\z/ end cross_reference name end ## # Handles rdoc-ref: scheme links and allows RDoc::Markup::ToHtml to # handle other schemes. def handle_special_HYPERLINK special return cross_reference $' if special.text =~ /\Ardoc-ref:/ super end ## # +special+ is an rdoc-schemed link that will be converted into a hyperlink. # For the rdoc-ref scheme the cross-reference will be looked up and the # given name will be used. # # All other contents are handled by # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_special_RDOCLINK] def handle_special_RDOCLINK special url = special.text case url when /\Ardoc-ref:/ then cross_reference $' else super end end ## # Generates links for rdoc-ref: scheme URLs and allows # RDoc::Markup::ToHtml to handle other schemes. def gen_url url, text return super unless url =~ /\Ardoc-ref:/ cross_reference $', text end ## # Creates an HTML link to +name+ with the given +text+. def link name, text original_name = name if name =~ /(.*[^#:])@/ then name = $1 label = $' end ref = @cross_reference.resolve name, text text = ref.output_name @context if RDoc::MethodAttr === ref and text == original_name case ref when String then ref else path = ref.as_href @from_path if path =~ /#/ then path << "-label-#{label}" else path << "#label-#{label}" end if label "#{text}" end end end rdoc/markup/inline.rb000064400000000130147635155430010604 0ustar00warn "requiring rdoc/markup/inline is deprecated and will be removed in RDoc 4." if $-w rdoc/markup/formatter.rb000064400000012452147635155430011343 0ustar00## # Base class for RDoc markup formatters # # Formatters are a visitor that converts an RDoc::Markup tree (from a comment) # into some kind of output. RDoc ships with formatters for converting back to # rdoc, ANSI text, HTML, a Table of Contents and other formats. # # If you'd like to write your own Formatter use # RDoc::Markup::FormatterTestCase. If you're writing a text-output formatter # use RDoc::Markup::TextFormatterTestCase which provides extra test cases. class RDoc::Markup::Formatter ## # Tag for inline markup containing a +bit+ for the bitmask and the +on+ and # +off+ triggers. InlineTag = Struct.new(:bit, :on, :off) ## # Converts a target url to one that is relative to a given path def self.gen_relative_url path, target from = File.dirname path to, to_file = File.split target from = from.split "/" to = to.split "/" from.delete '.' to.delete '.' while from.size > 0 and to.size > 0 and from[0] == to[0] do from.shift to.shift end from.fill ".." from.concat to from << to_file File.join(*from) end ## # Creates a new Formatter def initialize options, markup = nil @options = options @markup = markup || RDoc::Markup.new @am = @markup.attribute_manager @am.add_special(/
    /, :HARD_BREAK) @attributes = @am.attributes @attr_tags = [] @in_tt = 0 @tt_bit = @attributes.bitmap_for :TT @hard_break = '' @from_path = '.' end ## # Adds +document+ to the output def accept_document document document.parts.each do |item| case item when RDoc::Markup::Document then # HACK accept_document item else item.accept self end end end ## # Adds a special for links of the form rdoc-...: def add_special_RDOCLINK @markup.add_special(/rdoc-[a-z]+:\S+/, :RDOCLINK) end ## # Adds a special for links of the form {}[] and [] def add_special_TIDYLINK @markup.add_special(/(?: \{.*?\} | # multi-word label \b[^\s{}]+? # single-word label ) \[\S+?\] # link target /x, :TIDYLINK) end ## # Add a new set of tags for an attribute. We allow separate start and end # tags for flexibility def add_tag(name, start, stop) attr = @attributes.bitmap_for name @attr_tags << InlineTag.new(attr, start, stop) end ## # Allows +tag+ to be decorated with additional information. def annotate(tag) tag end ## # Marks up +content+ def convert content @markup.convert content, self end ## # Converts flow items +flow+ def convert_flow(flow) res = [] flow.each do |item| case item when String then res << convert_string(item) when RDoc::Markup::AttrChanger then off_tags res, item on_tags res, item when RDoc::Markup::Special then res << convert_special(item) else raise "Unknown flow element: #{item.inspect}" end end res.join end ## # Converts added specials. See RDoc::Markup#add_special def convert_special special return special.text if in_tt? handled = false @attributes.each_name_of special.type do |name| method_name = "handle_special_#{name}" if respond_to? method_name then special.text = send method_name, special handled = true end end unless handled then special_name = @attributes.as_string special.type raise RDoc::Error, "Unhandled special #{special_name}: #{special}" end special.text end ## # Converts a string to be fancier if desired def convert_string string string end ## # Use ignore in your subclass to ignore the content of a node. # # ## # # We don't support raw nodes in ToNoRaw # # alias accept_raw ignore def ignore *node end ## # Are we currently inside tt tags? def in_tt? @in_tt > 0 end ## # Turns on tags for +item+ on +res+ def on_tags res, item attr_mask = item.turn_on return if attr_mask.zero? @attr_tags.each do |tag| if attr_mask & tag.bit != 0 then res << annotate(tag.on) @in_tt += 1 if tt? tag end end end ## # Turns off tags for +item+ on +res+ def off_tags res, item attr_mask = item.turn_off return if attr_mask.zero? @attr_tags.reverse_each do |tag| if attr_mask & tag.bit != 0 then @in_tt -= 1 if tt? tag res << annotate(tag.off) end end end ## # Extracts and a scheme, url and an anchor id from +url+ and returns them. def parse_url url case url when /^rdoc-label:([^:]*)(?::(.*))?/ then scheme = 'link' path = "##{$1}" id = " id=\"#{$2}\"" if $2 when /([A-Za-z]+):(.*)/ then scheme = $1.downcase path = $2 when /^#/ then else scheme = 'http' path = url url = "http://#{url}" end if scheme == 'link' then url = if path[0, 1] == '#' then # is this meaningful? path else self.class.gen_relative_url @from_path, path end end [scheme, url, id] end ## # Is +tag+ a tt tag? def tt? tag tag.bit == @tt_bit end end rdoc/markup/to_rdoc.rb000064400000014171147635155430010771 0ustar00## # Outputs RDoc markup as RDoc markup! (mostly) class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter ## # Current indent amount for output in characters attr_accessor :indent ## # Output width in characters attr_accessor :width ## # Stack of current list indexes for alphabetic and numeric lists attr_reader :list_index ## # Stack of list types attr_reader :list_type ## # Stack of list widths for indentation attr_reader :list_width ## # Prefix for the next list item. See #use_prefix attr_reader :prefix ## # Output accumulator attr_reader :res ## # Creates a new formatter that will output (mostly) \RDoc markup def initialize markup = nil super nil, markup @markup.add_special(/\\\S/, :SUPPRESSED_CROSSREF) @width = 78 init_tags @headings = {} @headings.default = [] @headings[1] = ['= ', ''] @headings[2] = ['== ', ''] @headings[3] = ['=== ', ''] @headings[4] = ['==== ', ''] @headings[5] = ['===== ', ''] @headings[6] = ['====== ', ''] @hard_break = "\n" end ## # Maps attributes to HTML sequences def init_tags add_tag :BOLD, "", "" add_tag :TT, "", "" add_tag :EM, "", "" end ## # Adds +blank_line+ to the output def accept_blank_line blank_line @res << "\n" end ## # Adds +paragraph+ to the output def accept_block_quote block_quote @indent += 2 block_quote.parts.each do |part| @prefix = '> ' part.accept self end @indent -= 2 end ## # Adds +heading+ to the output def accept_heading heading use_prefix or @res << ' ' * @indent @res << @headings[heading.level][0] @res << attributes(heading.text) @res << @headings[heading.level][1] @res << "\n" end ## # Finishes consumption of +list+ def accept_list_end list @list_index.pop @list_type.pop @list_width.pop end ## # Finishes consumption of +list_item+ def accept_list_item_end list_item width = case @list_type.last when :BULLET then 2 when :NOTE, :LABEL then if @prefix then @res << @prefix.strip @prefix = nil end @res << "\n" 2 else bullet = @list_index.last.to_s @list_index[-1] = @list_index.last.succ bullet.length + 2 end @indent -= width end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start list_item type = @list_type.last case type when :NOTE, :LABEL then bullets = Array(list_item.label).map do |label| attributes(label).strip end.join "\n" bullets << ":\n" unless bullets.empty? @prefix = ' ' * @indent @indent += 2 @prefix << bullets + (' ' * @indent) else bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.' @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1) width = bullet.length + 1 @indent += width end end ## # Prepares the visitor for consuming +list+ def accept_list_start list case list.type when :BULLET then @list_index << nil @list_width << 1 when :LABEL, :NOTE then @list_index << nil @list_width << 2 when :LALPHA then @list_index << 'a' @list_width << list.items.length.to_s.length when :NUMBER then @list_index << 1 @list_width << list.items.length.to_s.length when :UALPHA then @list_index << 'A' @list_width << list.items.length.to_s.length else raise RDoc::Error, "invalid list type #{list.type}" end @list_type << list.type end ## # Adds +paragraph+ to the output def accept_paragraph paragraph text = paragraph.text @hard_break wrap attributes text end ## # Adds +paragraph+ to the output def accept_indented_paragraph paragraph @indent += paragraph.indent text = paragraph.text @hard_break wrap attributes text @indent -= paragraph.indent end ## # Adds +raw+ to the output def accept_raw raw @res << raw.parts.join("\n") end ## # Adds +rule+ to the output def accept_rule rule use_prefix or @res << ' ' * @indent @res << '-' * (@width - @indent) @res << "\n" end ## # Outputs +verbatim+ indented 2 columns def accept_verbatim verbatim indent = ' ' * (@indent + 2) verbatim.parts.each do |part| @res << indent unless part == "\n" @res << part end @res << "\n" unless @res =~ /\n\z/ end ## # Applies attribute-specific markup to +text+ using RDoc::AttributeManager def attributes text flow = @am.flow text.dup convert_flow flow end ## # Returns the generated output def end_accepting @res.join end ## # Removes preceding \\ from the suppressed crossref +special+ def handle_special_SUPPRESSED_CROSSREF special text = special.text text = text.sub('\\', '') unless in_tt? text end ## # Adds a newline to the output def handle_special_HARD_BREAK special "\n" end ## # Prepares the visitor for text generation def start_accepting @res = [""] @indent = 0 @prefix = nil @list_index = [] @list_type = [] @list_width = [] end ## # Adds the stored #prefix to the output and clears it. Lists generate a # prefix for later consumption. def use_prefix prefix, @prefix = @prefix, nil @res << prefix if prefix prefix end ## # Wraps +text+ to #width def wrap text return unless text && !text.empty? text_len = @width - @indent text_len = 20 if text_len < 20 re = /^(.{0,#{text_len}})[ \n]/ next_prefix = ' ' * @indent prefix = @prefix || next_prefix @prefix = nil @res << prefix while text.length > text_len if text =~ re then @res << $1 text.slice!(0, $&.length) else @res << text.slice!(0, text_len) end @res << "\n" << next_prefix end if text.empty? then @res.pop @res.pop else @res << text @res << "\n" end end end rdoc/markup/to_markdown.rb000064400000007061147635155430011664 0ustar00# :markup: markdown ## # Outputs parsed markup as Markdown class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc ## # Creates a new formatter that will output Markdown format text def initialize markup = nil super @headings[1] = ['# ', ''] @headings[2] = ['## ', ''] @headings[3] = ['### ', ''] @headings[4] = ['#### ', ''] @headings[5] = ['##### ', ''] @headings[6] = ['###### ', ''] add_special_RDOCLINK add_special_TIDYLINK @hard_break = " \n" end ## # Maps attributes to HTML sequences def init_tags add_tag :BOLD, '**', '**' add_tag :EM, '*', '*' add_tag :TT, '`', '`' end ## # Adds a newline to the output def handle_special_HARD_BREAK special " \n" end ## # Finishes consumption of `list` def accept_list_end list @res << "\n" super end ## # Finishes consumption of `list_item` def accept_list_item_end list_item width = case @list_type.last when :BULLET then 4 when :NOTE, :LABEL then use_prefix 4 else @list_index[-1] = @list_index.last.succ 4 end @indent -= width end ## # Prepares the visitor for consuming `list_item` def accept_list_item_start list_item type = @list_type.last case type when :NOTE, :LABEL then bullets = Array(list_item.label).map do |label| attributes(label).strip end.join "\n" bullets << "\n:" @prefix = ' ' * @indent @indent += 4 @prefix << bullets + (' ' * (@indent - 1)) else bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.' @prefix = (' ' * @indent) + bullet.ljust(4) @indent += 4 end end ## # Prepares the visitor for consuming `list` def accept_list_start list case list.type when :BULLET, :LABEL, :NOTE then @list_index << nil when :LALPHA, :NUMBER, :UALPHA then @list_index << 1 else raise RDoc::Error, "invalid list type #{list.type}" end @list_width << 4 @list_type << list.type end ## # Adds `rule` to the output def accept_rule rule use_prefix or @res << ' ' * @indent @res << '-' * 3 @res << "\n" end ## # Outputs `verbatim` indented 4 columns def accept_verbatim verbatim indent = ' ' * (@indent + 4) verbatim.parts.each do |part| @res << indent unless part == "\n" @res << part end @res << "\n" unless @res =~ /\n\z/ end ## # Creates a Markdown-style URL from +url+ with +text+. def gen_url url, text scheme, url, = parse_url url "[#{text.sub(%r{^#{scheme}:/*}i, '')}](#{url})" end ## # Handles rdoc- type links for footnotes. def handle_rdoc_link url case url when /\Ardoc-ref:/ then $' when /\Ardoc-label:footmark-(\d+)/ then "[^#{$1}]:" when /\Ardoc-label:foottext-(\d+)/ then "[^#{$1}]" when /\Ardoc-label:label-/ then gen_url url, $' when /\Ardoc-[a-z]+:/ then $' end end ## # Converts the RDoc markup tidylink into a Markdown.style link. def handle_special_TIDYLINK special text = special.text return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/ label = $1 url = $2 if url =~ /^rdoc-label:foot/ then handle_rdoc_link url else gen_url url, label end end ## # Converts the rdoc-...: links into a Markdown.style links. def handle_special_RDOCLINK special handle_rdoc_link special.text end end rdoc/markup/parser.rb000064400000034034147635155430010634 0ustar00require 'strscan' ## # A recursive-descent parser for RDoc markup. # # The parser tokenizes an input string then parses the tokens into a Document. # Documents can be converted into output formats by writing a visitor like # RDoc::Markup::ToHTML. # # The parser only handles the block-level constructs Paragraph, List, # ListItem, Heading, Verbatim, BlankLine and Rule. Inline markup such as # \+blah\+ is handled separately by RDoc::Markup::AttributeManager. # # To see what markup the Parser implements read RDoc. To see how to use # RDoc markup to format text in your program read RDoc::Markup. class RDoc::Markup::Parser include RDoc::Text ## # List token types LIST_TOKENS = [ :BULLET, :LABEL, :LALPHA, :NOTE, :NUMBER, :UALPHA, ] ## # Parser error subclass class Error < RuntimeError; end ## # Raised when the parser is unable to handle the given markup class ParseError < Error; end ## # Enables display of debugging information attr_accessor :debug ## # Token accessor attr_reader :tokens ## # Parses +str+ into a Document. # # Use RDoc::Markup#parse instead of this method. def self.parse str parser = new parser.tokenize str doc = RDoc::Markup::Document.new parser.parse doc end ## # Returns a token stream for +str+, for testing def self.tokenize str parser = new parser.tokenize str parser.tokens end ## # Creates a new Parser. See also ::parse def initialize @binary_input = nil @current_token = nil @debug = false @have_encoding = Object.const_defined? :Encoding @have_byteslice = ''.respond_to? :byteslice @input = nil @input_encoding = nil @line = 0 @line_pos = 0 @s = nil @tokens = [] end ## # Builds a Heading of +level+ def build_heading level type, text, = get text = case type when :TEXT then skip :NEWLINE text else unget '' end RDoc::Markup::Heading.new level, text end ## # Builds a List flush to +margin+ def build_list margin p :list_start => margin if @debug list = RDoc::Markup::List.new label = nil until @tokens.empty? do type, data, column, = get case type when *LIST_TOKENS then if column < margin || (list.type && list.type != type) then unget break end list.type = type peek_type, _, column, = peek_token case type when :NOTE, :LABEL then label = [] unless label if peek_type == :NEWLINE then # description not on the same line as LABEL/NOTE # skip the trailing newline & any blank lines below while peek_type == :NEWLINE get peek_type, _, column, = peek_token end # we may be: # - at end of stream # - at a column < margin: # [text] # blah blah blah # - at the same column, but with a different type of list item # [text] # * blah blah # - at the same column, with the same type of list item # [one] # [two] # In all cases, we have an empty description. # In the last case only, we continue. if peek_type.nil? || column < margin then empty = true elsif column == margin then case peek_type when type empty = :continue when *LIST_TOKENS empty = true else empty = false end else empty = false end if empty then label << data next if empty == :continue break end end else data = nil end if label then data = label << data label = nil end list_item = RDoc::Markup::ListItem.new data parse list_item, column list << list_item else unget break end end p :list_end => margin if @debug if list.empty? then return nil unless label return nil unless [:LABEL, :NOTE].include? list.type list_item = RDoc::Markup::ListItem.new label, RDoc::Markup::BlankLine.new list << list_item end list end ## # Builds a Paragraph that is flush to +margin+ def build_paragraph margin p :paragraph_start => margin if @debug paragraph = RDoc::Markup::Paragraph.new until @tokens.empty? do type, data, column, = get if type == :TEXT and column == margin then paragraph << data break if peek_token.first == :BREAK data << ' ' if skip :NEWLINE else unget break end end paragraph.parts.last.sub!(/ \z/, '') # cleanup p :paragraph_end => margin if @debug paragraph end ## # Builds a Verbatim that is indented from +margin+. # # The verbatim block is shifted left (the least indented lines start in # column 0). Each part of the verbatim is one line of text, always # terminated by a newline. Blank lines always consist of a single newline # character, and there is never a single newline at the end of the verbatim. def build_verbatim margin p :verbatim_begin => margin if @debug verbatim = RDoc::Markup::Verbatim.new min_indent = nil generate_leading_spaces = true line = '' until @tokens.empty? do type, data, column, = get if type == :NEWLINE then line << data verbatim << line line = '' generate_leading_spaces = true next end if column <= margin unget break end if generate_leading_spaces then indent = column - margin line << ' ' * indent min_indent = indent if min_indent.nil? || indent < min_indent generate_leading_spaces = false end case type when :HEADER then line << '=' * data _, _, peek_column, = peek_token peek_column ||= column + data indent = peek_column - column - data line << ' ' * indent when :RULE then width = 2 + data line << '-' * width _, _, peek_column, = peek_token peek_column ||= column + width indent = peek_column - column - width line << ' ' * indent when :BREAK, :TEXT then line << data else # *LIST_TOKENS list_marker = case type when :BULLET then data when :LABEL then "[#{data}]" when :NOTE then "#{data}::" else # :LALPHA, :NUMBER, :UALPHA "#{data}." end line << list_marker peek_type, _, peek_column = peek_token unless peek_type == :NEWLINE then peek_column ||= column + list_marker.length indent = peek_column - column - list_marker.length line << ' ' * indent end end end verbatim << line << "\n" unless line.empty? verbatim.parts.each { |p| p.slice!(0, min_indent) unless p == "\n" } if min_indent > 0 verbatim.normalize p :verbatim_end => margin if @debug verbatim end ## # The character offset for the input string at the given +byte_offset+ def char_pos byte_offset if @have_byteslice then @input.byteslice(0, byte_offset).length elsif @have_encoding then matched = @binary_input[0, byte_offset] matched.force_encoding @input_encoding matched.length else byte_offset end end ## # Pulls the next token from the stream. def get @current_token = @tokens.shift p :get => @current_token if @debug @current_token end ## # Parses the tokens into an array of RDoc::Markup::XXX objects, # and appends them to the passed +parent+ RDoc::Markup::YYY object. # # Exits at the end of the token stream, or when it encounters a token # in a column less than +indent+ (unless it is a NEWLINE). # # Returns +parent+. def parse parent, indent = 0 p :parse_start => indent if @debug until @tokens.empty? do type, data, column, = get case type when :BREAK then parent << RDoc::Markup::BlankLine.new skip :NEWLINE, false next when :NEWLINE then # trailing newlines are skipped below, so this is a blank line parent << RDoc::Markup::BlankLine.new skip :NEWLINE, false next end # indentation change: break or verbatim if column < indent then unget break elsif column > indent then unget parent << build_verbatim(indent) next end # indentation is the same case type when :HEADER then parent << build_heading(data) when :RULE then parent << RDoc::Markup::Rule.new(data) skip :NEWLINE when :TEXT then unget parent << build_paragraph(indent) when *LIST_TOKENS then unget parent << build_list(indent) else type, data, column, line = @current_token raise ParseError, "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}" end end p :parse_end => indent if @debug parent end ## # Returns the next token on the stream without modifying the stream def peek_token token = @tokens.first || [] p :peek => token if @debug token end ## # Creates the StringScanner def setup_scanner input @line = 0 @line_pos = 0 @input = input.dup if @have_encoding and not @have_byteslice then @input_encoding = @input.encoding @binary_input = @input.force_encoding Encoding::BINARY end @s = StringScanner.new input end ## # Skips the next token if its type is +token_type+. # # Optionally raises an error if the next token is not of the expected type. def skip token_type, error = true type, = get return unless type # end of stream return @current_token if token_type == type unget raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if error end ## # Turns text +input+ into a stream of tokens def tokenize input setup_scanner input until @s.eos? do pos = @s.pos # leading spaces will be reflected by the column of the next token # the only thing we loose are trailing spaces at the end of the file next if @s.scan(/ +/) # note: after BULLET, LABEL, etc., # indent will be the column of the next non-newline token @tokens << case # [CR]LF => :NEWLINE when @s.scan(/\r?\n/) then token = [:NEWLINE, @s.matched, *token_pos(pos)] @line_pos = char_pos @s.pos @line += 1 token # === text => :HEADER then :TEXT when @s.scan(/(=+)(\s*)/) then level = @s[1].length header = [:HEADER, level, *token_pos(pos)] if @s[2] =~ /^\r?\n/ then @s.pos -= @s[2].length header else pos = @s.pos @s.scan(/.*/) @tokens << header [:TEXT, @s.matched.sub(/\r$/, ''), *token_pos(pos)] end # --- (at least 3) and nothing else on the line => :RULE when @s.scan(/(-{3,}) *\r?$/) then [:RULE, @s[1].length - 2, *token_pos(pos)] # * or - followed by white space and text => :BULLET when @s.scan(/([*-]) +(\S)/) then @s.pos -= @s[2].bytesize # unget \S [:BULLET, @s[1], *token_pos(pos)] # A. text, a. text, 12. text => :UALPHA, :LALPHA, :NUMBER when @s.scan(/([a-z]|\d+)\. +(\S)/i) then # FIXME if tab(s), the column will be wrong # either support tabs everywhere by first expanding them to # spaces, or assume that they will have been replaced # before (and provide a check for that at least in debug # mode) list_label = @s[1] @s.pos -= @s[2].bytesize # unget \S list_type = case list_label when /[a-z]/ then :LALPHA when /[A-Z]/ then :UALPHA when /\d/ then :NUMBER else raise ParseError, "BUG token #{list_label}" end [list_type, list_label, *token_pos(pos)] # [text] followed by spaces or end of line => :LABEL when @s.scan(/\[(.*?)\]( +|\r?$)/) then [:LABEL, @s[1], *token_pos(pos)] # text:: followed by spaces or end of line => :NOTE when @s.scan(/(.*?)::( +|\r?$)/) then [:NOTE, @s[1], *token_pos(pos)] # anything else: :TEXT else @s.scan(/(.*?)( )?\r?$/) token = [:TEXT, @s[1], *token_pos(pos)] if @s[2] then @tokens << token [:BREAK, @s[2], *token_pos(pos + @s[1].length)] else token end end end self end ## # Calculates the column (by character) and line of the current token from # +scanner+ based on +byte_offset+. def token_pos byte_offset offset = char_pos byte_offset [offset - @line_pos, @line] end ## # Returns the current token to the token stream def unget token = @current_token p :unget => token if @debug raise Error, 'too many #ungets' if token == @tokens.first @tokens.unshift token if token end end rdoc/markup/block_quote.rb000064400000000336147635155430011645 0ustar00## # A quoted section which contains markup items. class RDoc::Markup::BlockQuote < RDoc::Markup::Raw ## # Calls #accept_block_quote on +visitor+ def accept visitor visitor.accept_block_quote self end end rdoc/markup/special.rb000064400000001163147635155430010755 0ustar00## # Hold details of a special sequence class RDoc::Markup::Special ## # Special type attr_reader :type ## # Special text attr_accessor :text ## # Creates a new special sequence of +type+ with +text+ def initialize(type, text) @type, @text = type, text end ## # Specials are equal when the have the same text and type def ==(o) self.text == o.text && self.type == o.type end def inspect # :nodoc: "#" % [ object_id, @type, text.dump] end def to_s # :nodoc: "Special: type=#{type} text=#{text.dump}" end end rdoc/markup/to_bs.rb000064400000003257147635155430010451 0ustar00## # Outputs RDoc markup with hot backspace action! You will probably need a # pager to use this output format. # # This formatter won't work on 1.8.6 because it lacks String#chars. class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc ## # Returns a new ToBs that is ready for hot backspace action! def initialize markup = nil super @in_b = false @in_em = false end ## # Sets a flag that is picked up by #annotate to do the right thing in # #convert_string def init_tags add_tag :BOLD, '+b', '-b' add_tag :EM, '+_', '-_' add_tag :TT, '' , '' # we need in_tt information maintained end ## # Makes heading text bold. def accept_heading heading use_prefix or @res << ' ' * @indent @res << @headings[heading.level][0] @in_b = true @res << attributes(heading.text) @in_b = false @res << @headings[heading.level][1] @res << "\n" end ## # Turns on or off special handling for +convert_string+ def annotate tag case tag when '+b' then @in_b = true when '-b' then @in_b = false when '+_' then @in_em = true when '-_' then @in_em = false end '' end ## # Calls convert_string on the result of convert_special def convert_special special convert_string super end ## # Adds bold or underline mixed with backspaces def convert_string string return string unless string.respond_to? :chars # your ruby is lame return string unless @in_b or @in_em chars = if @in_b then string.chars.map do |char| "#{char}\b#{char}" end elsif @in_em then string.chars.map do |char| "_\b#{char}" end end chars.join end end rdoc/markup/pre_process.rb000064400000020217147635155430011662 0ustar00## # Handle common directives that can occur in a block of text: # # \:include: filename # # Directives can be escaped by preceding them with a backslash. # # RDoc plugin authors can register additional directives to be handled by # using RDoc::Markup::PreProcess::register. # # Any directive that is not built-in to RDoc (including those registered via # plugins) will be stored in the metadata hash on the CodeObject the comment # is attached to. See RDoc::Markup@Directives for the list of built-in # directives. class RDoc::Markup::PreProcess ## # An RDoc::Options instance that will be filled in with overrides from # directives attr_accessor :options ## # Adds a post-process handler for directives. The handler will be called # with the result RDoc::Comment (or text String) and the code object for the # comment (if any). def self.post_process &block @post_processors << block end ## # Registered post-processors def self.post_processors @post_processors end ## # Registers +directive+ as one handled by RDoc. If a block is given the # directive will be replaced by the result of the block, otherwise the # directive will be removed from the processed text. # # The block will be called with the directive name and the directive # parameter: # # RDoc::Markup::PreProcess.register 'my-directive' do |directive, param| # # replace text, etc. # end def self.register directive, &block @registered[directive] = block end ## # Registered directives def self.registered @registered end ## # Clears all registered directives and post-processors def self.reset @post_processors = [] @registered = {} end reset ## # Creates a new pre-processor for +input_file_name+ that will look for # included files in +include_path+ def initialize(input_file_name, include_path) @input_file_name = input_file_name @include_path = include_path @options = nil end ## # Look for directives in the given +text+. # # Options that we don't handle are yielded. If the block returns false the # directive is restored to the text. If the block returns nil or no block # was given the directive is handled according to the registered directives. # If a String was returned the directive is replaced with the string. # # If no matching directive was registered the directive is restored to the # text. # # If +code_object+ is given and the directive is unknown then the # directive's parameter is set as metadata on the +code_object+. See # RDoc::CodeObject#metadata for details. def handle text, code_object = nil, &block if RDoc::Comment === text then comment = text text = text.text end encoding = text.encoding if defined?(Encoding) # regexp helper (square brackets for optional) # $1 $2 $3 $4 $5 # [prefix][\]:directive:[spaces][param]newline text.gsub!(/^([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):(\w+):([ \t]*)(.+)?(\r?\n|$)/) do # skip something like ':toto::' next $& if $4.empty? and $5 and $5[0, 1] == ':' # skip if escaped next "#$1:#$3:#$4#$5\n" unless $2.empty? # This is not in handle_directive because I didn't want to pass another # argument into it if comment and $3 == 'markup' then next "#{$1.strip}\n" unless $5 comment.format = $5.downcase next "#{$1.strip}\n" end handle_directive $1, $3, $5, code_object, encoding, &block end comment = text unless comment self.class.post_processors.each do |handler| handler.call comment, code_object end text end ## # Performs the actions described by +directive+ and its parameter +param+. # # +code_object+ is used for directives that operate on a class or module. # +prefix+ is used to ensure the replacement for handled directives is # correct. +encoding+ is used for the include directive. # # For a list of directives in RDoc see RDoc::Markup. #-- # When 1.8.7 support is ditched prefix can be defaulted to '' def handle_directive prefix, directive, param, code_object = nil, encoding = nil blankline = "#{prefix.strip}\n" directive = directive.downcase case directive when 'arg', 'args' then return blankline unless code_object code_object.params = param blankline when 'category' then if RDoc::Context === code_object then section = code_object.add_section param code_object.temporary_section = section end blankline # ignore category if we're not on an RDoc::Context when 'doc' then return blankline unless code_object code_object.document_self = true code_object.force_documentation = true blankline when 'enddoc' then return blankline unless code_object code_object.done_documenting = true blankline when 'include' then filename = param.split.first include_file filename, prefix, encoding when 'main' then @options.main_page = param if @options.respond_to? :main_page blankline when 'nodoc' then return blankline unless code_object code_object.document_self = nil # notify nodoc code_object.document_children = param !~ /all/i blankline when 'notnew', 'not_new', 'not-new' then return blankline unless RDoc::AnyMethod === code_object code_object.dont_rename_initialize = true blankline when 'startdoc' then return blankline unless code_object code_object.start_doc code_object.force_documentation = true blankline when 'stopdoc' then return blankline unless code_object code_object.stop_doc blankline when 'title' then @options.default_title = param if @options.respond_to? :default_title= blankline when 'yield', 'yields' then return blankline unless code_object # remove parameter &block code_object.params.sub!(/,?\s*&\w+/, '') if code_object.params code_object.block_params = param blankline else result = yield directive, param if block_given? case result when nil then code_object.metadata[directive] = param if code_object if RDoc::Markup::PreProcess.registered.include? directive then handler = RDoc::Markup::PreProcess.registered[directive] result = handler.call directive, param if handler else result = "#{prefix}:#{directive}: #{param}\n" end when false then result = "#{prefix}:#{directive}: #{param}\n" end result end end ## # Handles the :include: _filename_ directive. # # If the first line of the included file starts with '#', and contains # an encoding information in the form 'coding:' or 'coding=', it is # removed. # # If all lines in the included file start with a '#', this leading '#' # is removed before inclusion. The included content is indented like # the :include: directive. #-- # so all content will be verbatim because of the likely space after '#'? # TODO shift left the whole file content in that case # TODO comment stop/start #-- and #++ in included file must be processed here def include_file name, indent, encoding full_name = find_include_file name unless full_name then warn "Couldn't find file to include '#{name}' from #{@input_file_name}" return '' end content = RDoc::Encoding.read_file full_name, encoding, true # strip magic comment content = content.sub(/\A# .*coding[=:].*$/, '').lstrip # strip leading '#'s, but only if all lines start with them if content =~ /^[^#]/ then content.gsub(/^/, indent) else content.gsub(/^#?/, indent) end end ## # Look for the given file in the directory containing the current file, # and then in each of the directories specified in the RDOC_INCLUDE path def find_include_file(name) to_search = [File.dirname(@input_file_name)].concat @include_path to_search.each do |dir| full_name = File.join(dir, name) stat = File.stat(full_name) rescue next return full_name if stat.readable? end nil end end rdoc/markup/to_ansi.rb000064400000004030147635155430010765 0ustar00## # Outputs RDoc markup with vibrant ANSI color! class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc ## # Creates a new ToAnsi visitor that is ready to output vibrant ANSI color! def initialize markup = nil super @headings.clear @headings[1] = ["\e[1;32m", "\e[m"] # bold @headings[2] = ["\e[4;32m", "\e[m"] # underline @headings[3] = ["\e[32m", "\e[m"] # just green end ## # Maps attributes to ANSI sequences def init_tags add_tag :BOLD, "\e[1m", "\e[m" add_tag :TT, "\e[7m", "\e[m" add_tag :EM, "\e[4m", "\e[m" end ## # Overrides indent width to ensure output lines up correctly. def accept_list_item_end list_item width = case @list_type.last when :BULLET then 2 when :NOTE, :LABEL then if @prefix then @res << @prefix.strip @prefix = nil end @res << "\n" unless res.length == 1 2 else bullet = @list_index.last.to_s @list_index[-1] = @list_index.last.succ bullet.length + 2 end @indent -= width end ## # Adds coloring to note and label list items def accept_list_item_start list_item bullet = case @list_type.last when :BULLET then '*' when :NOTE, :LABEL then labels = Array(list_item.label).map do |label| attributes(label).strip end.join "\n" labels << ":\n" unless labels.empty? labels else @list_index.last.to_s + '.' end case @list_type.last when :NOTE, :LABEL then @indent += 2 @prefix = bullet + (' ' * @indent) else @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1) width = bullet.gsub(/\e\[[\d;]*m/, '').length + 1 @indent += width end end ## # Starts accepting with a reset screen def start_accepting super @res = ["\e[0m"] end end rdoc/markup/to_table_of_contents.rb000064400000003231147635155430013525 0ustar00## # Extracts just the RDoc::Markup::Heading elements from a # RDoc::Markup::Document to help build a table of contents class RDoc::Markup::ToTableOfContents < RDoc::Markup::Formatter @to_toc = nil ## # Singleton for table-of-contents generation def self.to_toc @to_toc ||= new end ## # Output accumulator attr_reader :res ## # Omits headings with a level less than the given level. attr_accessor :omit_headings_below def initialize # :nodoc: super nil @omit_headings_below = nil end ## # Adds +document+ to the output, using its heading cutoff if present def accept_document document @omit_headings_below = document.omit_headings_below super end ## # Adds +heading+ to the table of contents def accept_heading heading @res << heading unless suppressed? heading end ## # Returns the table of contents def end_accepting @res end ## # Prepares the visitor for text generation def start_accepting @omit_headings_below = nil @res = [] end ## # Returns true if +heading+ is below the display threshold def suppressed? heading return false unless @omit_headings_below heading.level > @omit_headings_below end # :stopdoc: alias accept_block_quote ignore alias accept_raw ignore alias accept_rule ignore alias accept_blank_line ignore alias accept_paragraph ignore alias accept_verbatim ignore alias accept_list_end ignore alias accept_list_item_start ignore alias accept_list_item_end ignore alias accept_list_end_bullet ignore alias accept_list_start ignore # :startdoc: end rdoc/markup/indented_paragraph.rb000064400000001554147635155430013160 0ustar00## # An Indented Paragraph of text class RDoc::Markup::IndentedParagraph < RDoc::Markup::Raw ## # The indent in number of spaces attr_reader :indent ## # Creates a new IndentedParagraph containing +parts+ indented with +indent+ # spaces def initialize indent, *parts @indent = indent super(*parts) end def == other # :nodoc: super and indent == other.indent end ## # Calls #accept_indented_paragraph on +visitor+ def accept visitor visitor.accept_indented_paragraph self end ## # Joins the raw paragraph text and converts inline HardBreaks to the # +hard_break+ text followed by the indent. def text hard_break = nil @parts.map do |part| if RDoc::Markup::HardBreak === part then '%1$s%3$*2$s' % [hard_break, @indent, ' '] if hard_break else part end end.join end end rdoc/markup/attributes.rb000064400000002240147635155430011520 0ustar00## # We manage a set of attributes. Each attribute has a symbol name and a bit # value. class RDoc::Markup::Attributes ## # The special attribute type. See RDoc::Markup#add_special attr_reader :special ## # Creates a new attributes set. def initialize @special = 1 @name_to_bitmap = [ [:_SPECIAL_, @special], ] @next_bitmap = @special << 1 end ## # Returns a unique bit for +name+ def bitmap_for name bitmap = @name_to_bitmap.assoc name unless bitmap then bitmap = @next_bitmap @next_bitmap <<= 1 @name_to_bitmap << [name, bitmap] else bitmap = bitmap.last end bitmap end ## # Returns a string representation of +bitmap+ def as_string bitmap return 'none' if bitmap.zero? res = [] @name_to_bitmap.each do |name, bit| res << name if (bitmap & bit) != 0 end res.join ',' end ## # yields each attribute name in +bitmap+ def each_name_of bitmap return enum_for __method__, bitmap unless block_given? @name_to_bitmap.each do |name, bit| next if bit == @special yield name.to_s if (bitmap & bit) != 0 end end end rdoc/markup/list_item.rb000064400000003274147635155430011333 0ustar00## # An item within a List that contains paragraphs, headings, etc. # # For BULLET, NUMBER, LALPHA and UALPHA lists, the label will always be nil. # For NOTE and LABEL lists, the list label may contain: # # * a single String for a single label # * an Array of Strings for a list item with multiple terms # * nil for an extra description attached to a previously labeled list item class RDoc::Markup::ListItem ## # The label for the ListItem attr_accessor :label ## # Parts of the ListItem attr_reader :parts ## # Creates a new ListItem with an optional +label+ containing +parts+ def initialize label = nil, *parts @label = label @parts = [] @parts.concat parts end ## # Appends +part+ to the ListItem def << part @parts << part end def == other # :nodoc: self.class == other.class and @label == other.label and @parts == other.parts end ## # Runs this list item and all its #parts through +visitor+ def accept visitor visitor.accept_list_item_start self @parts.each do |part| part.accept visitor end visitor.accept_list_item_end self end ## # Is the ListItem empty? def empty? @parts.empty? end ## # Length of parts in the ListItem def length @parts.length end def pretty_print q # :nodoc: q.group 2, '[item: ', ']' do case @label when Array then q.pp @label q.text ';' q.breakable when String then q.pp @label q.text ';' q.breakable end q.seplist @parts do |part| q.pp part end end end ## # Adds +parts+ to the ListItem def push *parts @parts.concat parts end end rdoc/markup/text_formatter_test_case.rb000064400000004761147635155430014445 0ustar00## # Test case for creating new plain-text RDoc::Markup formatters. See also # RDoc::Markup::FormatterTestCase # # See test_rdoc_markup_to_rdoc.rb for a complete example. # # Example: # # class TestRDocMarkupToNewTextFormat < RDoc::Markup::TextFormatterTestCase # # add_visitor_tests # add_text_tests # # def setup # super # # @to = RDoc::Markup::ToNewTextFormat.new # end # # def accept_blank_line # assert_equal :junk, @to.res.join # end # # # ... # # end class RDoc::Markup::TextFormatterTestCase < RDoc::Markup::FormatterTestCase ## # Adds test cases to the calling TestCase. def self.add_text_tests self.class_eval do ## # Test case that calls @to.accept_heading def test_accept_heading_indent @to.start_accepting @to.indent = 3 @to.accept_heading @RM::Heading.new(1, 'Hello') accept_heading_indent end ## # Test case that calls @to.accept_rule def test_accept_rule_indent @to.start_accepting @to.indent = 3 @to.accept_rule @RM::Rule.new(1) accept_rule_indent end ## # Test case that calls @to.accept_verbatim def test_accept_verbatim_indent @to.start_accepting @to.indent = 2 @to.accept_verbatim @RM::Verbatim.new("hi\n", " world\n") accept_verbatim_indent end ## # Test case that calls @to.accept_verbatim with a big indent def test_accept_verbatim_big_indent @to.start_accepting @to.indent = 2 @to.accept_verbatim @RM::Verbatim.new("hi\n", "world\n") accept_verbatim_big_indent end ## # Test case that calls @to.accept_paragraph with an indent def test_accept_paragraph_indent @to.start_accepting @to.indent = 3 @to.accept_paragraph @RM::Paragraph.new(('words ' * 30).strip) accept_paragraph_indent end ## # Test case that calls @to.accept_paragraph with a long line def test_accept_paragraph_wrap @to.start_accepting @to.accept_paragraph @RM::Paragraph.new(('words ' * 30).strip) accept_paragraph_wrap end ## # Test case that calls @to.attributes with an escaped # cross-reference. If this test doesn't pass something may be very # wrong. def test_attributes assert_equal 'Dog', @to.attributes("\\Dog") end end end end rdoc/markup/attribute_manager.rb000064400000017527147635155430013045 0ustar00## # Manages changes of attributes in a block of text class RDoc::Markup::AttributeManager ## # The NUL character NULL = "\000".freeze #-- # We work by substituting non-printing characters in to the text. For now # I'm assuming that I can substitute a character in the range 0..8 for a 7 # bit character without damaging the encoded string, but this might be # optimistic #++ A_PROTECT = 004 # :nodoc: ## # Special mask character to prevent inline markup handling PROTECT_ATTR = A_PROTECT.chr # :nodoc: ## # The attributes enabled for this markup object. attr_reader :attributes ## # This maps delimiters that occur around words (such as *bold* or +tt+) # where the start and end delimiters and the same. This lets us optimize # the regexp attr_reader :matching_word_pairs ## # And this is used when the delimiters aren't the same. In this case the # hash maps a pattern to the attribute character attr_reader :word_pair_map ## # This maps HTML tags to the corresponding attribute char attr_reader :html_tags ## # A \ in front of a character that would normally be processed turns off # processing. We do this by turning \< into <#{PROTECT} attr_reader :protectable ## # And this maps _special_ sequences to a name. A special sequence is # something like a WikiWord attr_reader :special ## # Creates a new attribute manager that understands bold, emphasized and # teletype text. def initialize @html_tags = {} @matching_word_pairs = {} @protectable = %w[<] @special = [] @word_pair_map = {} @attributes = RDoc::Markup::Attributes.new add_word_pair "*", "*", :BOLD add_word_pair "_", "_", :EM add_word_pair "+", "+", :TT add_html "em", :EM add_html "i", :EM add_html "b", :BOLD add_html "tt", :TT add_html "code", :TT end ## # Return an attribute object with the given turn_on and turn_off bits set def attribute(turn_on, turn_off) RDoc::Markup::AttrChanger.new turn_on, turn_off end ## # Changes the current attribute from +current+ to +new+ def change_attribute current, new diff = current ^ new attribute(new & diff, current & diff) end ## # Used by the tests to change attributes by name from +current_set+ to # +new_set+ def changed_attribute_by_name current_set, new_set current = new = 0 current_set.each do |name| current |= @attributes.bitmap_for(name) end new_set.each do |name| new |= @attributes.bitmap_for(name) end change_attribute(current, new) end ## # Copies +start_pos+ to +end_pos+ from the current string def copy_string(start_pos, end_pos) res = @str[start_pos...end_pos] res.gsub!(/\000/, '') res end ## # Map attributes like textto the sequence # \001\002\001\003, where is a per-attribute specific # character def convert_attrs(str, attrs) # first do matching ones tags = @matching_word_pairs.keys.join("") re = /(^|\W)([#{tags}])([#:\\]?[\w.\/-]+?\S?)\2(\W|$)/ 1 while str.gsub!(re) do attr = @matching_word_pairs[$2] attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr) $1 + NULL * $2.length + $3 + NULL * $2.length + $4 end # then non-matching unless @word_pair_map.empty? then @word_pair_map.each do |regexp, attr| str.gsub!(regexp) { attrs.set_attrs($`.length + $1.length, $2.length, attr) NULL * $1.length + $2 + NULL * $3.length } end end end ## # Converts HTML tags to RDoc attributes def convert_html(str, attrs) tags = @html_tags.keys.join '|' 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { attr = @html_tags[$1.downcase] html_length = $1.length + 2 seq = NULL * html_length attrs.set_attrs($`.length + html_length, $2.length, attr) seq + $2 + seq + NULL } end ## # Converts special sequences to RDoc attributes def convert_specials str, attrs @special.each do |regexp, attribute| str.scan(regexp) do capture = $~.size == 1 ? 0 : 1 s, e = $~.offset capture attrs.set_attrs s, e - s, attribute | @attributes.special end end end ## # Escapes special sequences of text to prevent conversion to RDoc def mask_protected_sequences # protect __send__, __FILE__, etc. @str.gsub!(/__([a-z]+)__/i, "_#{PROTECT_ATTR}_#{PROTECT_ATTR}\\1_#{PROTECT_ATTR}_#{PROTECT_ATTR}") @str.gsub!(/\\([#{Regexp.escape @protectable.join('')}])/, "\\1#{PROTECT_ATTR}") end ## # Unescapes special sequences of text def unmask_protected_sequences @str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000") end ## # Adds a markup class with +name+ for words wrapped in the +start+ and # +stop+ character. To make words wrapped with "*" bold: # # am.add_word_pair '*', '*', :BOLD def add_word_pair(start, stop, name) raise ArgumentError, "Word flags may not start with '<'" if start[0,1] == '<' bitmap = @attributes.bitmap_for name if start == stop then @matching_word_pairs[start] = bitmap else pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/ @word_pair_map[pattern] = bitmap end @protectable << start[0,1] @protectable.uniq! end ## # Adds a markup class with +name+ for words surrounded by HTML tag +tag+. # To process emphasis tags: # # am.add_html 'em', :EM def add_html(tag, name) @html_tags[tag.downcase] = @attributes.bitmap_for name end ## # Adds a special handler for +pattern+ with +name+. A simple URL handler # would be: # # @am.add_special(/((https?:)\S+\w)/, :HYPERLINK) def add_special pattern, name @special << [pattern, @attributes.bitmap_for(name)] end ## # Processes +str+ converting attributes, HTML and specials def flow str @str = str mask_protected_sequences @attrs = RDoc::Markup::AttrSpan.new @str.length convert_attrs @str, @attrs convert_html @str, @attrs convert_specials @str, @attrs unmask_protected_sequences split_into_flow end ## # Debug method that prints a string along with its attributes def display_attributes puts puts @str.tr(NULL, "!") bit = 1 16.times do |bno| line = "" @str.length.times do |i| if (@attrs[i] & bit) == 0 line << " " else if bno.zero? line << "S" else line << ("%d" % (bno+1)) end end end puts(line) unless line =~ /^ *$/ bit <<= 1 end end ## # Splits the string into chunks by attribute change def split_into_flow res = [] current_attr = 0 str_len = @str.length # skip leading invisible text i = 0 i += 1 while i < str_len and @str[i].chr == "\0" start_pos = i # then scan the string, chunking it on attribute changes while i < str_len new_attr = @attrs[i] if new_attr != current_attr if i > start_pos res << copy_string(start_pos, i) start_pos = i end res << change_attribute(current_attr, new_attr) current_attr = new_attr if (current_attr & @attributes.special) != 0 then i += 1 while i < str_len and (@attrs[i] & @attributes.special) != 0 res << RDoc::Markup::Special.new(current_attr, copy_string(start_pos, i)) start_pos = i next end end # move on, skipping any invisible characters begin i += 1 end while i < str_len and @str[i].chr == "\0" end # tidy up trailing text if start_pos < str_len res << copy_string(start_pos, str_len) end # and reset to all attributes off res << change_attribute(current_attr, 0) if current_attr != 0 res end end rdoc/markup/list.rb000064400000003447147635155430010317 0ustar00## # A List is a homogeneous set of ListItems. # # The supported list types include: # # :BULLET:: # An unordered list # :LABEL:: # An unordered definition list, but using an alternate RDoc::Markup syntax # :LALPHA:: # An ordered list using increasing lowercase English letters # :NOTE:: # An unordered definition list # :NUMBER:: # An ordered list using increasing Arabic numerals # :UALPHA:: # An ordered list using increasing uppercase English letters # # Definition lists behave like HTML definition lists. Each list item can # describe multiple terms. See RDoc::Markup::ListItem for how labels and # definition are stored as list items. class RDoc::Markup::List ## # The list's type attr_accessor :type ## # Items in the list attr_reader :items ## # Creates a new list of +type+ with +items+. Valid list types are: # +:BULLET+, +:LABEL+, +:LALPHA+, +:NOTE+, +:NUMBER+, +:UALPHA+ def initialize type = nil, *items @type = type @items = [] @items.concat items end ## # Appends +item+ to the list def << item @items << item end def == other # :nodoc: self.class == other.class and @type == other.type and @items == other.items end ## # Runs this list and all its #items through +visitor+ def accept visitor visitor.accept_list_start self @items.each do |item| item.accept visitor end visitor.accept_list_end self end ## # Is the list empty? def empty? @items.empty? end ## # Returns the last item in the list def last @items.last end def pretty_print q # :nodoc: q.group 2, "[list: #{@type} ", ']' do q.seplist @items do |item| q.pp item end end end ## # Appends +items+ to the list def push *items @items.concat items end end rdoc/markup/to_test.rb000064400000002160147635155430011014 0ustar00## # This Markup outputter is used for testing purposes. class RDoc::Markup::ToTest < RDoc::Markup::Formatter # :stopdoc: ## # :section: Visitor def start_accepting @res = [] @list = [] end def end_accepting @res end def accept_paragraph(paragraph) @res << convert_flow(@am.flow(paragraph.text)) end def accept_raw raw @res << raw.parts.join end def accept_verbatim(verbatim) @res << verbatim.text.gsub(/^(\S)/, ' \1') end def accept_list_start(list) @list << case list.type when :BULLET then '*' when :NUMBER then '1' else list.type end end def accept_list_end(list) @list.pop end def accept_list_item_start(list_item) @res << "#{' ' * (@list.size - 1)}#{@list.last}: " end def accept_list_item_end(list_item) end def accept_blank_line(blank_line) @res << "\n" end def accept_heading(heading) @res << "#{'=' * heading.level} #{heading.text}" end def accept_rule(rule) @res << '-' * rule.weight end # :startdoc: end rdoc/markup/to_joined_paragraph.rb000064400000003062147635155430013334 0ustar00## # Joins the parts of an RDoc::Markup::Paragraph into a single String. # # This allows for easier maintenance and testing of Markdown support. # # This formatter only works on Paragraph instances. Attempting to process # other markup syntax items will not work. class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter def initialize # :nodoc: super nil end def start_accepting # :nodoc: end def end_accepting # :nodoc: end ## # Converts the parts of +paragraph+ to a single entry. def accept_paragraph paragraph parts = [] string = false paragraph.parts.each do |part| if String === part then if string then string << part else parts << part string = part end else parts << part string = false end end parts = parts.map do |part| if String === part then part.rstrip else part end end # TODO use Enumerable#chunk when ruby 1.8 support is dropped #parts = paragraph.parts.chunk do |part| # String === part #end.map do |string, chunk| # string ? chunk.join.rstrip : chunk #end.flatten paragraph.parts.replace parts end alias accept_block_quote ignore alias accept_heading ignore alias accept_list_end ignore alias accept_list_item_end ignore alias accept_list_item_start ignore alias accept_list_start ignore alias accept_raw ignore alias accept_rule ignore alias accept_verbatim ignore end rdoc/markup/blank_line.rb000064400000000551147635155430011433 0ustar00## # An empty line. This class is a singleton. class RDoc::Markup::BlankLine @instance = new ## # RDoc::Markup::BlankLine is a singleton def self.new @instance end ## # Calls #accept_blank_line on +visitor+ def accept visitor visitor.accept_blank_line self end def pretty_print q # :nodoc: q.text 'blankline' end end rdoc/markup/heading.rb000064400000002255147635155430010737 0ustar00## # A heading with a level (1-6) and text RDoc::Markup::Heading = Struct.new :level, :text do @to_html = nil @to_label = nil ## # A singleton RDoc::Markup::ToLabel formatter for headings. def self.to_label @to_label ||= RDoc::Markup::ToLabel.new end ## # A singleton plain HTML formatter for headings. Used for creating labels # for the Table of Contents def self.to_html return @to_html if @to_html markup = RDoc::Markup.new markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF @to_html = RDoc::Markup::ToHtml.new nil def @to_html.handle_special_CROSSREF special special.text.sub(/^\\/, '') end @to_html end ## # Calls #accept_heading on +visitor+ def accept visitor visitor.accept_heading self end ## # An HTML-safe anchor reference for this header. def aref "label-#{self.class.to_label.convert text.dup}" end ## # HTML markup of the text of this label without the surrounding header # element. def plain_html self.class.to_html.to_html(text.dup) end def pretty_print q # :nodoc: q.group 2, "[head: #{level} ", ']' do q.pp text end end end rdoc/markup/attr_span.rb000064400000000726147635155430011334 0ustar00## # An array of attributes which parallels the characters in a string. class RDoc::Markup::AttrSpan ## # Creates a new AttrSpan for +length+ characters def initialize(length) @attrs = Array.new(length, 0) end ## # Toggles +bits+ from +start+ to +length+ def set_attrs(start, length, bits) for i in start ... (start+length) @attrs[i] |= bits end end ## # Accesses flags for character +n+ def [](n) @attrs[n] end end rdoc/markup/attr_changer.rb000064400000000612147635155430011774 0ustar00class RDoc::Markup AttrChanger = Struct.new :turn_on, :turn_off # :nodoc: end ## # An AttrChanger records a change in attributes. It contains a bitmap of the # attributes to turn on, and a bitmap of those to turn off. class RDoc::Markup::AttrChanger def to_s # :nodoc: "Attr: +#{turn_on}/-#{turn_off}" end def inspect # :nodoc: '+%d/-%d' % [turn_on, turn_off] end end rdoc/markup/to_html_snippet.rb000064400000012660147635155430012551 0ustar00## # Outputs RDoc markup as paragraphs with inline markup only. class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml ## # After this many characters the input will be cut off. attr_reader :character_limit ## # The number of characters seen so far. attr_reader :characters # :nodoc: ## # The attribute bitmask attr_reader :mask ## # After this many paragraphs the input will be cut off. attr_reader :paragraph_limit ## # Count of paragraphs found attr_reader :paragraphs ## # Creates a new ToHtmlSnippet formatter that will cut off the input on the # next word boundary after the given number of +characters+ or +paragraphs+ # of text have been encountered. def initialize options, characters = 100, paragraphs = 3, markup = nil super options, markup @character_limit = characters @paragraph_limit = paragraphs @characters = 0 @mask = 0 @paragraphs = 0 @markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF end ## # Adds +heading+ to the output as a paragraph def accept_heading heading @res << "

    #{to_html heading.text}\n" add_paragraph end ## # Raw sections are untrusted and ignored alias accept_raw ignore ## # Rules are ignored alias accept_rule ignore def accept_paragraph paragraph para = @in_list_entry.last || "

    " text = paragraph.text @hard_break @res << "#{para}#{wrap to_html text}\n" add_paragraph end ## # Finishes consumption of +list_item+ def accept_list_item_end list_item end ## # Prepares the visitor for consuming +list_item+ def accept_list_item_start list_item @res << list_item_start(list_item, @list.last) end ## # Prepares the visitor for consuming +list+ def accept_list_start list @list << list.type @res << html_list_name(list.type, true) @in_list_entry.push '' end ## # Adds +verbatim+ to the output def accept_verbatim verbatim throw :done if @characters >= @character_limit input = verbatim.text.rstrip text = truncate input text << ' ...' unless text == input super RDoc::Markup::Verbatim.new text add_paragraph end ## # Prepares the visitor for HTML snippet generation def start_accepting super @characters = 0 end ## # Removes escaping from the cross-references in +special+ def handle_special_CROSSREF special special.text.sub(/\A\\/, '') end ## # +special+ is a
    def handle_special_HARD_BREAK special @characters -= 4 '
    ' end ## # Lists are paragraphs, but notes and labels have a separator def list_item_start list_item, list_type throw :done if @characters >= @character_limit case list_type when :BULLET, :LALPHA, :NUMBER, :UALPHA then "

    " when :LABEL, :NOTE then labels = Array(list_item.label).map do |label| to_html label end.join ', ' labels << " — " unless labels.empty? start = "

    #{labels}" @characters += 1 # try to include the label start else raise RDoc::Error, "Invalid list type: #{list_type.inspect}" end end ## # Returns just the text of +link+, +url+ is only used to determine the link # type. def gen_url url, text if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then type = "link" elsif url =~ /([A-Za-z]+):(.*)/ then type = $1 else type = "http" end if (type == "http" or type == "https" or type == "link") and url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then '' else text.sub(%r%^#{type}:/*%, '') end end ## # In snippets, there are no lists def html_list_name list_type, open_tag '' end ## # Throws +:done+ when paragraph_limit paragraphs have been encountered def add_paragraph @paragraphs += 1 throw :done if @paragraphs >= @paragraph_limit end ## # Marks up +content+ def convert content catch :done do return super end end_accepting end ## # Converts flow items +flow+ def convert_flow flow throw :done if @characters >= @character_limit res = [] @mask = 0 flow.each do |item| case item when RDoc::Markup::AttrChanger then off_tags res, item on_tags res, item when String then text = convert_string item res << truncate(text) when RDoc::Markup::Special then text = convert_special item res << truncate(text) else raise "Unknown flow element: #{item.inspect}" end if @characters >= @character_limit then off_tags res, RDoc::Markup::AttrChanger.new(0, @mask) break end end res << ' ...' if @characters >= @character_limit res.join end ## # Maintains a bitmask to allow HTML elements to be closed properly. See # RDoc::Markup::Formatter. def on_tags res, item @mask ^= item.turn_on super end ## # Maintains a bitmask to allow HTML elements to be closed properly. See # RDoc::Markup::Formatter. def off_tags res, item @mask ^= item.turn_off super end ## # Truncates +text+ at the end of the first word after the character_limit. def truncate text length = text.length characters = @characters @characters += length return text if @characters < @character_limit remaining = @character_limit - characters text =~ /\A(.{#{remaining},}?)(\s|$)/m # TODO word-break instead of \s? $1 end end rdoc/markup/formatter_test_case.rb000064400000041541147635155430013376 0ustar00require 'minitest/unit' ## # Test case for creating new RDoc::Markup formatters. See # test/test_rdoc_markup_to_*.rb for examples. # # This test case adds a variety of tests to your subclass when # #add_visitor_tests is called. Most tests set up a scenario then call a # method you will provide to perform the assertion on the output. # # Your subclass must instantiate a visitor and assign it to @to. # # For example, test_accept_blank_line sets up a RDoc::Markup::BlockLine then # calls accept_blank_line on your visitor. You are responsible for asserting # that the output is correct. # # Example: # # class TestRDocMarkupToNewFormat < RDoc::Markup::FormatterTestCase # # add_visitor_tests # # def setup # super # # @to = RDoc::Markup::ToNewFormat.new # end # # def accept_blank_line # assert_equal :junk, @to.res.join # end # # # ... # # end class RDoc::Markup::FormatterTestCase < RDoc::TestCase ## # Call #setup when inheriting from this test case. # # Provides the following instance variables: # # +@m+:: RDoc::Markup.new # +@RM+:: RDoc::Markup # to reduce typing # +@bullet_list+:: @RM::List.new :BULLET, # ... # +@label_list+:: @RM::List.new :LABEL, # ... # +@lalpha_list+:: @RM::List.new :LALPHA, # ... # +@note_list+:: @RM::List.new :NOTE, # ... # +@number_list+:: @RM::List.new :NUMBER, # ... # +@ualpha_list+:: @RM::List.new :UALPHA, # ... def setup super @options = RDoc::Options.new @m = @RM.new @bullet_list = @RM::List.new(:BULLET, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) @label_list = @RM::List.new(:LABEL, @RM::ListItem.new('cat', @RM::Paragraph.new('cats are cool')), @RM::ListItem.new('dog', @RM::Paragraph.new('dogs are cool too'))) @lalpha_list = @RM::List.new(:LALPHA, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) @note_list = @RM::List.new(:NOTE, @RM::ListItem.new('cat', @RM::Paragraph.new('cats are cool')), @RM::ListItem.new('dog', @RM::Paragraph.new('dogs are cool too'))) @number_list = @RM::List.new(:NUMBER, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) @ualpha_list = @RM::List.new(:UALPHA, @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) end ## # Call to add the visitor tests to your test case def self.add_visitor_tests class_eval do ## # Calls start_accepting which needs to verify startup state def test_start_accepting @to.start_accepting start_accepting end ## # Calls end_accepting on your test case which needs to call # @to.end_accepting and verify document generation def test_end_accepting @to.start_accepting @to.res << 'hi' end_accepting end ## # Calls accept_blank_line def test_accept_blank_line @to.start_accepting @to.accept_blank_line @RM::BlankLine.new accept_blank_line end ## # Calls accept_block_quote def test_accept_block_quote @to.start_accepting @to.accept_block_quote block para 'quote' accept_block_quote end ## # Test case that calls @to.accept_document def test_accept_document @to.start_accepting @to.accept_document @RM::Document.new @RM::Paragraph.new 'hello' accept_document end ## # Calls accept_heading with a level 5 RDoc::Markup::Heading def test_accept_heading @to.start_accepting @to.accept_heading @RM::Heading.new(5, 'Hello') accept_heading end ## # Calls accept_heading_1 with a level 1 RDoc::Markup::Heading def test_accept_heading_1 @to.start_accepting @to.accept_heading @RM::Heading.new(1, 'Hello') accept_heading_1 end ## # Calls accept_heading_2 with a level 2 RDoc::Markup::Heading def test_accept_heading_2 @to.start_accepting @to.accept_heading @RM::Heading.new(2, 'Hello') accept_heading_2 end ## # Calls accept_heading_3 with a level 3 RDoc::Markup::Heading def test_accept_heading_3 # HACK this doesn't belong here skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars @to.start_accepting @to.accept_heading @RM::Heading.new(3, 'Hello') accept_heading_3 end ## # Calls accept_heading_4 with a level 4 RDoc::Markup::Heading def test_accept_heading_4 @to.start_accepting @to.accept_heading @RM::Heading.new(4, 'Hello') accept_heading_4 end ## # Calls accept_heading_b with a bold level 1 RDoc::Markup::Heading def test_accept_heading_b @to.start_accepting @to.accept_heading @RM::Heading.new(1, '*Hello*') accept_heading_b end ## # Calls accept_heading_suppressed_crossref with a level 1 # RDoc::Markup::Heading containing a suppressed crossref def test_accept_heading_suppressed_crossref # HACK to_html_crossref test @to.start_accepting @to.accept_heading @RM::Heading.new(1, '\\Hello') accept_heading_suppressed_crossref end ## # Calls accept_paragraph def test_accept_paragraph @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('hi') accept_paragraph end ## # Calls accept_paragraph_b with a RDoc::Markup::Paragraph containing # bold words def test_accept_paragraph_b @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg bold words reg') accept_paragraph_b end ## # Calls accept_paragraph_br with a RDoc::Markup::Paragraph containing # a \
    def test_accept_paragraph_br @to.start_accepting @to.accept_paragraph para 'one
    two' accept_paragraph_br end ## # Calls accept_paragraph with a Paragraph containing a hard break def test_accept_paragraph_break @to.start_accepting @to.accept_paragraph para('hello', hard_break, 'world') accept_paragraph_break end ## # Calls accept_paragraph_i with a RDoc::Markup::Paragraph containing # emphasized words def test_accept_paragraph_i @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg italic words reg') accept_paragraph_i end ## # Calls accept_paragraph_plus with a RDoc::Markup::Paragraph containing # teletype words def test_accept_paragraph_plus @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg +teletype+ reg') accept_paragraph_plus end ## # Calls accept_paragraph_star with a RDoc::Markup::Paragraph containing # bold words def test_accept_paragraph_star @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg *bold* reg') accept_paragraph_star end ## # Calls accept_paragraph_underscore with a RDoc::Markup::Paragraph # containing emphasized words def test_accept_paragraph_underscore @to.start_accepting @to.accept_paragraph @RM::Paragraph.new('reg _italic_ reg') accept_paragraph_underscore end ## # Calls accept_verbatim with a RDoc::Markup::Verbatim def test_accept_verbatim @to.start_accepting @to.accept_verbatim @RM::Verbatim.new("hi\n", " world\n") accept_verbatim end ## # Calls accept_raw with a RDoc::Markup::Raw def test_accept_raw @to.start_accepting @to.accept_raw @RM::Raw.new("", "
    NameCount", "
    a1", "
    b2", "
    ") accept_raw end ## # Calls accept_rule with a RDoc::Markup::Rule def test_accept_rule @to.start_accepting @to.accept_rule @RM::Rule.new(4) accept_rule end ## # Calls accept_list_item_start_bullet def test_accept_list_item_start_bullet @to.start_accepting @to.accept_list_start @bullet_list @to.accept_list_item_start @bullet_list.items.first accept_list_item_start_bullet end ## # Calls accept_list_item_start_label def test_accept_list_item_start_label @to.start_accepting @to.accept_list_start @label_list @to.accept_list_item_start @label_list.items.first accept_list_item_start_label end ## # Calls accept_list_item_start_lalpha def test_accept_list_item_start_lalpha @to.start_accepting @to.accept_list_start @lalpha_list @to.accept_list_item_start @lalpha_list.items.first accept_list_item_start_lalpha end ## # Calls accept_list_item_start_note def test_accept_list_item_start_note @to.start_accepting @to.accept_list_start @note_list @to.accept_list_item_start @note_list.items.first accept_list_item_start_note end ## # Calls accept_list_item_start_note_2 def test_accept_list_item_start_note_2 list = list(:NOTE, item('teletype', para('teletype description'))) @to.start_accepting list.accept @to @to.end_accepting accept_list_item_start_note_2 end ## # Calls accept_list_item_start_note_multi_description def test_accept_list_item_start_note_multi_description list = list(:NOTE, item(%w[label], para('description one')), item(nil, para('description two'))) @to.start_accepting list.accept @to @to.end_accepting accept_list_item_start_note_multi_description end ## # Calls accept_list_item_start_note_multi_label def test_accept_list_item_start_note_multi_label list = list(:NOTE, item(%w[one two], para('two headers'))) @to.start_accepting list.accept @to @to.end_accepting accept_list_item_start_note_multi_label end ## # Calls accept_list_item_start_number def test_accept_list_item_start_number @to.start_accepting @to.accept_list_start @number_list @to.accept_list_item_start @number_list.items.first accept_list_item_start_number end ## # Calls accept_list_item_start_ualpha def test_accept_list_item_start_ualpha @to.start_accepting @to.accept_list_start @ualpha_list @to.accept_list_item_start @ualpha_list.items.first accept_list_item_start_ualpha end ## # Calls accept_list_item_end_bullet def test_accept_list_item_end_bullet @to.start_accepting @to.accept_list_start @bullet_list @to.accept_list_item_start @bullet_list.items.first @to.accept_list_item_end @bullet_list.items.first accept_list_item_end_bullet end ## # Calls accept_list_item_end_label def test_accept_list_item_end_label @to.start_accepting @to.accept_list_start @label_list @to.accept_list_item_start @label_list.items.first @to.accept_list_item_end @label_list.items.first accept_list_item_end_label end ## # Calls accept_list_item_end_lalpha def test_accept_list_item_end_lalpha @to.start_accepting @to.accept_list_start @lalpha_list @to.accept_list_item_start @lalpha_list.items.first @to.accept_list_item_end @lalpha_list.items.first accept_list_item_end_lalpha end ## # Calls accept_list_item_end_note def test_accept_list_item_end_note @to.start_accepting @to.accept_list_start @note_list @to.accept_list_item_start @note_list.items.first @to.accept_list_item_end @note_list.items.first accept_list_item_end_note end ## # Calls accept_list_item_end_number def test_accept_list_item_end_number @to.start_accepting @to.accept_list_start @number_list @to.accept_list_item_start @number_list.items.first @to.accept_list_item_end @number_list.items.first accept_list_item_end_number end ## # Calls accept_list_item_end_ualpha def test_accept_list_item_end_ualpha @to.start_accepting @to.accept_list_start @ualpha_list @to.accept_list_item_start @ualpha_list.items.first @to.accept_list_item_end @ualpha_list.items.first accept_list_item_end_ualpha end ## # Calls accept_list_start_bullet def test_accept_list_start_bullet @to.start_accepting @to.accept_list_start @bullet_list accept_list_start_bullet end ## # Calls accept_list_start_label def test_accept_list_start_label @to.start_accepting @to.accept_list_start @label_list accept_list_start_label end ## # Calls accept_list_start_lalpha def test_accept_list_start_lalpha @to.start_accepting @to.accept_list_start @lalpha_list accept_list_start_lalpha end ## # Calls accept_list_start_note def test_accept_list_start_note @to.start_accepting @to.accept_list_start @note_list accept_list_start_note end ## # Calls accept_list_start_number def test_accept_list_start_number @to.start_accepting @to.accept_list_start @number_list accept_list_start_number end ## # Calls accept_list_start_ualpha def test_accept_list_start_ualpha @to.start_accepting @to.accept_list_start @ualpha_list accept_list_start_ualpha end ## # Calls accept_list_end_bullet def test_accept_list_end_bullet @to.start_accepting @to.accept_list_start @bullet_list @to.accept_list_end @bullet_list accept_list_end_bullet end ## # Calls accept_list_end_label def test_accept_list_end_label @to.start_accepting @to.accept_list_start @label_list @to.accept_list_end @label_list accept_list_end_label end ## # Calls accept_list_end_lalpha def test_accept_list_end_lalpha @to.start_accepting @to.accept_list_start @lalpha_list @to.accept_list_end @lalpha_list accept_list_end_lalpha end ## # Calls accept_list_end_number def test_accept_list_end_number @to.start_accepting @to.accept_list_start @number_list @to.accept_list_end @number_list accept_list_end_number end ## # Calls accept_list_end_note def test_accept_list_end_note @to.start_accepting @to.accept_list_start @note_list @to.accept_list_end @note_list accept_list_end_note end ## # Calls accept_list_end_ualpha def test_accept_list_end_ualpha @to.start_accepting @to.accept_list_start @ualpha_list @to.accept_list_end @ualpha_list accept_list_end_ualpha end ## # Calls list_nested with a two-level list def test_list_nested doc = @RM::Document.new( @RM::List.new(:BULLET, @RM::ListItem.new(nil, @RM::Paragraph.new('l1'), @RM::List.new(:BULLET, @RM::ListItem.new(nil, @RM::Paragraph.new('l1.1')))), @RM::ListItem.new(nil, @RM::Paragraph.new('l2')))) doc.accept @to list_nested end ## # Calls list_verbatim with a list containing a verbatim block def test_list_verbatim # HACK overblown doc = doc( list(:BULLET, item(nil, para('list stuff'), blank_line, verb("* list\n", " with\n", "\n", " second\n", "\n", " 1. indented\n", " 2. numbered\n", "\n", " third\n", "\n", "* second\n")))) doc.accept @to list_verbatim end end end end rdoc/markup/include.rb000064400000001437147635155430010764 0ustar00## # A file included at generation time. Objects of this class are created by # RDoc::RD for an extension-less include. # # This implementation in incomplete. class RDoc::Markup::Include ## # The filename to be included, without extension attr_reader :file ## # Directories to search for #file attr_reader :include_path ## # Creates a new include that will import +file+ from +include_path+ def initialize file, include_path @file = file @include_path = include_path end def == other # :nodoc: self.class === other and @file == other.file and @include_path == other.include_path end def pretty_print q # :nodoc: q.group 2, '[incl ', ']' do q.text file q.breakable q.text 'from ' q.pp include_path end end end rdoc/constant.rb000064400000006541147635155430007674 0ustar00## # A constant class RDoc::Constant < RDoc::CodeObject MARSHAL_VERSION = 0 # :nodoc: ## # Sets the module or class this is constant is an alias for. attr_writer :is_alias_for ## # The constant's name attr_accessor :name ## # The constant's value attr_accessor :value ## # The constant's visibility attr_accessor :visibility ## # Creates a new constant with +name+, +value+ and +comment+ def initialize(name, value, comment) super() @name = name @value = value @is_alias_for = nil @visibility = nil self.comment = comment end ## # Constants are ordered by name def <=> other return unless self.class === other [parent_name, name] <=> [other.parent_name, other.name] end ## # Constants are equal when their #parent and #name is the same def == other self.class == other.class and @parent == other.parent and @name == other.name end ## # A constant is documented if it has a comment, or is an alias # for a documented class or module. def documented? super or is_alias_for && is_alias_for.documented? end ## # Full constant name including namespace def full_name @full_name ||= "#{parent_name}::#{@name}" end ## # The module or class this constant is an alias for def is_alias_for case @is_alias_for when String then found = @store.find_class_or_module @is_alias_for @is_alias_for = found if found @is_alias_for else @is_alias_for end end def inspect # :nodoc: "#<%s:0x%x %s::%s>" % [ self.class, object_id, parent_name, @name, ] end ## # Dumps this Constant for use by ri. See also #marshal_load def marshal_dump alias_name = case found = is_alias_for when RDoc::CodeObject then found.full_name else found end [ MARSHAL_VERSION, @name, full_name, @visibility, alias_name, parse(@comment), @file.relative_name, parent.name, parent.class, section.title, ] end ## # Loads this Constant from +array+. For a loaded Constant the following # methods will return cached values: # # * #full_name # * #parent_name def marshal_load array initialize array[1], nil, array[5] @full_name = array[2] @visibility = array[3] @is_alias_for = array[4] # 5 handled above # 6 handled below @parent_name = array[7] @parent_class = array[8] @section_title = array[9] @file = RDoc::TopLevel.new array[6] end ## # Path to this constant for use with HTML generator output. def path "#{@parent.path}##{@name}" end def pretty_print q # :nodoc: q.group 2, "[#{self.class.name} #{full_name}", "]" do unless comment.empty? then q.breakable q.text "comment:" q.breakable q.pp @comment end end end ## # Sets the store for this class or module and its contained code objects. def store= store super @file = @store.add_file @file.full_name if @file end def to_s # :nodoc: parent_name = parent ? parent.full_name : '(unknown)' if is_alias_for "constant #{parent_name}::#@name -> #{is_alias_for}" else "constant #{parent_name}::#@name" end end end rdoc/comment.rb000064400000012624147635155430007504 0ustar00## # A comment holds the text comment for a RDoc::CodeObject and provides a # unified way of cleaning it up and parsing it into an RDoc::Markup::Document. # # Each comment may have a different markup format set by #format=. By default # 'rdoc' is used. The :markup: directive tells RDoc which format to use. # # See RDoc::Markup@Other+directives for instructions on adding an alternate # format. class RDoc::Comment include RDoc::Text ## # The format of this comment. Defaults to RDoc::Markup attr_reader :format ## # The RDoc::TopLevel this comment was found in attr_accessor :location ## # For duck-typing when merging classes at load time alias file location # :nodoc: ## # The text for this comment attr_reader :text ## # Overrides the content returned by #parse. Use when there is no #text # source for this comment attr_writer :document ## # Creates a new comment with +text+ that is found in the RDoc::TopLevel # +location+. def initialize text = nil, location = nil @location = location @text = text @document = nil @format = 'rdoc' @normalized = false end ## #-- # TODO deep copy @document def initialize_copy copy # :nodoc: @text = copy.text.dup end def == other # :nodoc: self.class === other and other.text == @text and other.location == @location end ## # Look for a 'call-seq' in the comment to override the normal parameter # handling. The :call-seq: is indented from the baseline. All lines of the # same indentation level and prefix are consumed. # # For example, all of the following will be used as the :call-seq: # # # :call-seq: # # ARGF.readlines(sep=$/) -> array # # ARGF.readlines(limit) -> array # # ARGF.readlines(sep, limit) -> array # # # # ARGF.to_a(sep=$/) -> array # # ARGF.to_a(limit) -> array # # ARGF.to_a(sep, limit) -> array def extract_call_seq method # we must handle situations like the above followed by an unindented first # comment. The difficulty is to make sure not to match lines starting # with ARGF at the same indent, but that are after the first description # paragraph. if @text =~ /^\s*:?call-seq:(.*?(?:\S).*?)^\s*$/m then all_start, all_stop = $~.offset(0) seq_start, seq_stop = $~.offset(1) # we get the following lines that start with the leading word at the # same indent, even if they have blank lines before if $1 =~ /(^\s*\n)+^(\s*\w+)/m then leading = $2 # ' * ARGF' in the example above re = %r% \A( (^\s*\n)+ (^#{Regexp.escape leading}.*?\n)+ )+ ^\s*$ %xm if @text[seq_stop..-1] =~ re then all_stop = seq_stop + $~.offset(0).last seq_stop = seq_stop + $~.offset(1).last end end seq = @text[seq_start..seq_stop] seq.gsub!(/^\s*(\S|\n)/m, '\1') @text.slice! all_start...all_stop method.call_seq = seq.chomp elsif @text.sub!(/^\s*:?call-seq:(.*?)(^\s*$|\z)/m, '') then seq = $1 seq.gsub!(/^\s*/, '') method.call_seq = seq end #elsif @text.sub!(/\A\/\*\s*call-seq:(.*?)\*\/\Z/, '') then # method.call_seq = $1.strip #end method end ## # A comment is empty if its text String is empty. def empty? @text.empty? end ## # HACK dubious def force_encoding encoding @text.force_encoding encoding end ## # Sets the format of this comment and resets any parsed document def format= format @format = format @document = nil end def inspect # :nodoc: location = @location ? @location.relative_name : '(unknown)' "#<%s:%x %s %p>" % [self.class, object_id, location, @text] end ## # Normalizes the text. See RDoc::Text#normalize_comment for details def normalize return self unless @text return self if @normalized # TODO eliminate duplicate normalization @text = normalize_comment @text @normalized = true self end ## # Was this text normalized? def normalized? # :nodoc: @normalized end ## # Parses the comment into an RDoc::Markup::Document. The parsed document is # cached until the text is changed. def parse return @document if @document @document = super @text, @format @document.file = @location @document end ## # Removes private sections from this comment. Private sections are flush to # the comment marker and start with -- and end with ++. # For C-style comments, a private marker may not start at the opening of the # comment. # # /* # *-- # * private # *++ # * public # */ def remove_private # Workaround for gsub encoding for Ruby 1.9.2 and earlier empty = '' empty.force_encoding @text.encoding if Object.const_defined? :Encoding @text = @text.gsub(%r%^\s*([#*]?)--.*?^\s*(\1)\+\+\n?%m, empty) @text = @text.sub(%r%^\s*[#*]?--.*%m, '') end ## # Replaces this comment's text with +text+ and resets the parsed document. # # An error is raised if the comment contains a document but no text. def text= text raise RDoc::Error, 'replacing document-only comment is not allowed' if @text.nil? and @document @document = nil @text = text end ## # Returns true if this comment is in TomDoc format. def tomdoc? @format == 'tomdoc' end end rdoc/ruby_token.rb000064400000026333147635155430010225 0ustar00#-- # 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 rdoc/anon_class.rb000064400000000216147635155430010154 0ustar00## # An anonymous class like: # # c = Class.new do end # # AnonClass is currently not used. class RDoc::AnonClass < RDoc::ClassModule end rdoc/rdoc.rb000064400000032411147635155430006765 0ustar00require 'rdoc' require 'find' require 'fileutils' require 'pathname' require 'time' ## # This is the driver for generating RDoc output. It handles file parsing and # generation of output. # # To use this class to generate RDoc output via the API, the recommended way # is: # # rdoc = RDoc::RDoc.new # options = rdoc.load_options # returns an RDoc::Options instance # # set extra options # rdoc.document options # # You can also generate output like the +rdoc+ executable: # # rdoc = RDoc::RDoc.new # rdoc.document argv # # Where +argv+ is an array of strings, each corresponding to an argument you'd # give rdoc on the command line. See rdoc --help for details. class RDoc::RDoc @current = nil ## # This is the list of supported output generators GENERATORS = {} ## # File pattern to exclude attr_accessor :exclude ## # Generator instance used for creating output attr_accessor :generator ## # Hash of files and their last modified times. attr_reader :last_modified ## # RDoc options attr_accessor :options ## # Accessor for statistics. Available after each call to parse_files attr_reader :stats ## # The current documentation store attr_reader :store ## # Add +klass+ that can generate output after parsing def self.add_generator(klass) name = klass.name.sub(/^RDoc::Generator::/, '').downcase GENERATORS[name] = klass end ## # Active RDoc::RDoc instance def self.current @current end ## # Sets the active RDoc::RDoc instance def self.current= rdoc @current = rdoc end ## # Creates a new RDoc::RDoc instance. Call #document to parse files and # generate documentation. def initialize @current = nil @exclude = nil @generator = nil @last_modified = {} @old_siginfo = nil @options = nil @stats = nil @store = nil end ## # Report an error message and exit def error(msg) raise RDoc::Error, msg end ## # Gathers a set of parseable files from the files and directories listed in # +files+. def gather_files files files = ["."] if files.empty? file_list = normalized_file_list files, true, @exclude file_list = file_list.uniq file_list = remove_unparseable file_list file_list.sort end ## # Turns RDoc from stdin into HTML def handle_pipe @html = RDoc::Markup::ToHtml.new @options parser = RDoc::Text::MARKUP_FORMAT[@options.markup] document = parser.parse $stdin.read out = @html.convert document $stdout.write out end ## # Installs a siginfo handler that prints the current filename. def install_siginfo_handler return unless Signal.list.include? 'INFO' @old_siginfo = trap 'INFO' do puts @current if @current end end ## # Loads options from .rdoc_options if the file exists, otherwise creates a # new RDoc::Options instance. def load_options options_file = File.expand_path '.rdoc_options' return RDoc::Options.new unless File.exist? options_file RDoc.load_yaml parse_error = if Object.const_defined? :Psych then Psych::SyntaxError else ArgumentError end begin options = YAML.load_file '.rdoc_options' rescue *parse_error end raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless RDoc::Options === options options end ## # Create an output dir if it doesn't exist. If it does exist, but doesn't # contain the flag file created.rid then we refuse to use it, as # we may clobber some manually generated documentation def setup_output_dir(dir, force) flag_file = output_flag_file dir last = {} if @options.dry_run then # do nothing elsif File.exist? dir then error "#{dir} exists and is not a directory" unless File.directory? dir begin open flag_file do |io| unless force then Time.parse io.gets io.each do |line| file, time = line.split "\t", 2 time = Time.parse(time) rescue next last[file] = time end end end rescue SystemCallError, TypeError error <<-ERROR Directory #{dir} already exists, but it looks like it isn't an RDoc directory. Because RDoc doesn't want to risk destroying any of your existing files, you'll need to specify a different output directory name (using the --op

    option) ERROR end unless @options.force_output else FileUtils.mkdir_p dir FileUtils.touch output_flag_file dir end last end ## # Sets the current documentation tree to +store+ and sets the store's rdoc # driver to this instance. def store= store @store = store @store.rdoc = self end ## # Update the flag file in an output directory. def update_output_dir(op_dir, time, last = {}) return if @options.dry_run or not @options.update_output_dir open output_flag_file(op_dir), "w" do |f| f.puts time.rfc2822 last.each do |n, t| f.puts "#{n}\t#{t.rfc2822}" end end end ## # Return the path name of the flag file in an output directory. def output_flag_file(op_dir) File.join op_dir, "created.rid" end ## # The .document file contains a list of file and directory name patterns, # representing candidates for documentation. It may also contain comments # (starting with '#') def parse_dot_doc_file in_dir, filename # read and strip comments patterns = File.read(filename).gsub(/#.*/, '') result = [] patterns.split.each do |patt| candidates = Dir.glob(File.join(in_dir, patt)) result.concat normalized_file_list(candidates) end result end ## # Given a list of files and directories, create a list of all the Ruby # files they contain. # # If +force_doc+ is true we always add the given files, if false, only # add files that we guarantee we can parse. It is true when looking at # files given on the command line, false when recursing through # subdirectories. # # The effect of this is that if you want a file with a non-standard # extension parsed, you must name it explicitly. def normalized_file_list(relative_files, force_doc = false, exclude_pattern = nil) file_list = [] relative_files.each do |rel_file_name| next if exclude_pattern && exclude_pattern =~ rel_file_name stat = File.stat rel_file_name rescue next case type = stat.ftype when "file" then next if last_modified = @last_modified[rel_file_name] and stat.mtime.to_i <= last_modified.to_i if force_doc or RDoc::Parser.can_parse(rel_file_name) then file_list << rel_file_name.sub(/^\.\//, '') @last_modified[rel_file_name] = stat.mtime end when "directory" then next if rel_file_name == "CVS" || rel_file_name == ".svn" dot_doc = File.join rel_file_name, RDoc::DOT_DOC_FILENAME if File.file? dot_doc then file_list << parse_dot_doc_file(rel_file_name, dot_doc) else file_list << list_files_in_directory(rel_file_name) end else warn "rdoc can't parse the #{type} #{rel_file_name}" end end file_list.flatten end ## # Return a list of the files to be processed in a directory. We know that # this directory doesn't have a .document file, so we're looking for real # files. However we may well contain subdirectories which must be tested # for .document files. def list_files_in_directory dir files = Dir.glob File.join(dir, "*") normalized_file_list files, false, @options.exclude end ## # Parses +filename+ and returns an RDoc::TopLevel def parse_file filename if defined?(Encoding) then encoding = @options.encoding filename = filename.encode encoding end @stats.add_file filename content = RDoc::Encoding.read_file filename, encoding return unless content filename_path = Pathname(filename).expand_path relative_path = filename_path.relative_path_from @options.root if @options.page_dir and relative_path.to_s.start_with? @options.page_dir.to_s then relative_path = relative_path.relative_path_from @options.page_dir end top_level = @store.add_file filename, relative_path.to_s parser = RDoc::Parser.for top_level, filename, content, @options, @stats return unless parser parser.scan # restart documentation for the classes & modules found top_level.classes_or_modules.each do |cm| cm.done_documenting = false end top_level rescue Errno::EACCES => e $stderr.puts <<-EOF Unable to read #{filename}, #{e.message} Please check the permissions for this file. Perhaps you do not have access to it or perhaps the original author's permissions are to restrictive. If the this is not your library please report a bug to the author. EOF rescue => e $stderr.puts <<-EOF Before reporting this, could you check that the file you're documenting has proper syntax: #{Gem.ruby} -c #{filename} RDoc is not a full Ruby parser and will fail when fed invalid ruby programs. The internal error was: \t(#{e.class}) #{e.message} EOF $stderr.puts e.backtrace.join("\n\t") if $DEBUG_RDOC raise e nil end ## # Parse each file on the command line, recursively entering directories. def parse_files files file_list = gather_files files @stats = RDoc::Stats.new @store, file_list.length, @options.verbosity return [] if file_list.empty? file_info = [] @stats.begin_adding file_info = file_list.map do |filename| @current = filename parse_file filename end.compact @stats.done_adding file_info end ## # Removes file extensions known to be unparseable from +files+ and TAGS # files for emacs and vim. def remove_unparseable files files.reject do |file| file =~ /\.(?:class|eps|erb|scpt\.txt|ttf|yml)$/i or (file =~ /tags$/i and File.open(file, 'rb') { |io| io.read(100) =~ /\A(\f\n[^,]+,\d+$|!_TAG_)/ }) end end ## # Generates documentation or a coverage report depending upon the settings # in +options+. # # +options+ can be either an RDoc::Options instance or an array of strings # equivalent to the strings that would be passed on the command line like # %w[-q -o doc -t My\ Doc\ Title]. #document will automatically # call RDoc::Options#finish if an options instance was given. # # For a list of options, see either RDoc::Options or rdoc --help. # # By default, output will be stored in a directory called "doc" below the # current directory, so make sure you're somewhere writable before invoking. def document options self.store = RDoc::Store.new if RDoc::Options === options then @options = options @options.finish else @options = load_options @options.parse options end if @options.pipe then handle_pipe exit end @exclude = @options.exclude unless @options.coverage_report then @last_modified = setup_output_dir @options.op_dir, @options.force_update end @store.encoding = @options.encoding if @options.respond_to? :encoding @store.dry_run = @options.dry_run @store.main = @options.main_page @store.title = @options.title @store.path = @options.op_dir @start_time = Time.now @store.load_cache file_info = parse_files @options.files @options.default_title = "RDoc Documentation" @store.complete @options.visibility @stats.coverage_level = @options.coverage_report if @options.coverage_report then puts puts @stats.report elsif file_info.empty? then $stderr.puts "\nNo newer files." unless @options.quiet else gen_klass = @options.generator @generator = gen_klass.new @store, @options generate end if @stats and (@options.coverage_report or not @options.quiet) then puts puts @stats.summary end exit @stats.fully_documented? if @options.coverage_report end ## # Generates documentation for +file_info+ (from #parse_files) into the # output dir using the generator selected # by the RDoc options def generate Dir.chdir @options.op_dir do unless @options.quiet then $stderr.puts "\nGenerating #{@generator.class.name.sub(/^.*::/, '')} format into #{Dir.pwd}..." end @generator.generate update_output_dir '.', @start_time, @last_modified end end ## # Removes a siginfo handler and replaces the previous def remove_siginfo_handler return unless Signal.list.key? 'INFO' handler = @old_siginfo || 'DEFAULT' trap 'INFO', handler end end begin require 'rubygems' if Gem.respond_to? :find_files then rdoc_extensions = Gem.find_files 'rdoc/discover' rdoc_extensions.each do |extension| begin load extension rescue => e warn "error loading #{extension.inspect}: #{e.message} (#{e.class})" warn "\t#{e.backtrace.join "\n\t"}" if $DEBUG end end end rescue LoadError end # require built-in generators after discovery in case they've been replaced require 'rdoc/generator/darkfish' require 'rdoc/generator/ri' rdoc/any_method.rb000064400000013633147635155430010172 0ustar00## # AnyMethod is the base class for objects representing methods class RDoc::AnyMethod < RDoc::MethodAttr ## # 2:: # RDoc 4 # Added calls_super # Added parent name and class # Added section title MARSHAL_VERSION = 2 # :nodoc: ## # Don't rename \#initialize to \::new attr_accessor :dont_rename_initialize ## # The C function that implements this method (if it was defined in a C file) attr_accessor :c_function ## # Different ways to call this method attr_accessor :call_seq ## # Parameters for this method attr_accessor :params ## # If true this method uses +super+ to call a superclass version attr_accessor :calls_super include RDoc::TokenStream ## # Creates a new AnyMethod with a token stream +text+ and +name+ def initialize text, name super @c_function = nil @dont_rename_initialize = false @token_stream = nil @calls_super = false @superclass_method = nil end ## # Adds +an_alias+ as an alias for this method in +context+. def add_alias an_alias, context = nil method = self.class.new an_alias.text, an_alias.new_name method.record_location an_alias.file method.singleton = self.singleton method.params = self.params method.visibility = self.visibility method.comment = an_alias.comment method.is_alias_for = self @aliases << method context.add_method method if context method end ## # Prefix for +aref+ is 'method'. def aref_prefix 'method' end ## # The call_seq or the param_seq with method name, if there is no call_seq. # # Use this for displaying a method's argument lists. def arglists if @call_seq then @call_seq elsif @params then "#{name}#{param_seq}" end end ## # Dumps this AnyMethod for use by ri. See also #marshal_load def marshal_dump aliases = @aliases.map do |a| [a.name, parse(a.comment)] end [ MARSHAL_VERSION, @name, full_name, @singleton, @visibility, parse(@comment), @call_seq, @block_params, aliases, @params, @file.relative_name, @calls_super, @parent.name, @parent.class, @section.title, ] end ## # Loads this AnyMethod from +array+. For a loaded AnyMethod the following # methods will return cached values: # # * #full_name # * #parent_name def marshal_load array initialize_visibility @dont_rename_initialize = nil @is_alias_for = nil @token_stream = nil @aliases = [] @parent = nil @parent_name = nil @parent_class = nil @section = nil @file = nil version = array[0] @name = array[1] @full_name = array[2] @singleton = array[3] @visibility = array[4] @comment = array[5] @call_seq = array[6] @block_params = array[7] # 8 handled below @params = array[9] # 10 handled below @calls_super = array[11] @parent_name = array[12] @parent_title = array[13] @section_title = array[14] array[8].each do |new_name, comment| add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton) end @parent_name ||= if @full_name =~ /#/ then $` else name = @full_name.split('::') name.pop name.join '::' end @file = RDoc::TopLevel.new array[10] if version > 0 end ## # Method name # # If the method has no assigned name, it extracts it from #call_seq. def name return @name if @name @name = @call_seq[/^.*?\.(\w+)/, 1] || @call_seq if @call_seq end ## # A list of this method's method and yield parameters. +call-seq+ params # are preferred over parsed method and block params. def param_list if @call_seq then params = @call_seq.split("\n").last params = params.sub(/.*?\((.*)\)/, '\1') params = params.sub(/(\{|do)\s*\|([^|]*)\|.*/, ',\2') elsif @params then params = @params.sub(/\((.*)\)/, '\1') params << ",#{@block_params}" if @block_params elsif @block_params then params = @block_params else return [] end params = params.gsub(/\s+/, '').split ',' params.map { |param| param.sub(/=.*/, '') } end ## # Pretty parameter list for this method. If the method's parameters were # given by +call-seq+ it is preferred over the parsed values. def param_seq if @call_seq then params = @call_seq.split("\n").last params = params.sub(/[^( ]+/, '') params = params.sub(/(\|[^|]+\|)\s*\.\.\.\s*(end|\})/, '\1 \2') elsif @params then params = @params.gsub(/\s*\#.*/, '') params = params.tr("\n", " ").squeeze(" ") params = "(#{params})" unless params[0] == ?( else params = '' end if @block_params then # If this method has explicit block parameters, remove any explicit # &block params.sub!(/,?\s*&\w+/, '') block = @block_params.gsub(/\s*\#.*/, '') block = block.tr("\n", " ").squeeze(" ") if block[0] == ?( block.sub!(/^\(/, '').sub!(/\)/, '') end params << " { |#{block}| ... }" end params end ## # Sets the store for this method and its referenced code objects. def store= store super @file = @store.add_file @file.full_name if @file end ## # For methods that +super+, find the superclass method that would be called. def superclass_method return unless @calls_super return @superclass_method if @superclass_method parent.each_ancestor do |ancestor| if method = ancestor.method_list.find { |m| m.name == @name } then @superclass_method = method break end end @superclass_method end end rdoc/tom_doc.rb000064400000013310147635155430007457 0ustar00# :markup: tomdoc # A parser for TomDoc based on TomDoc 1.0.0-rc1 (02adef9b5a) # # The TomDoc specification can be found at: # # http://tomdoc.org # # The latest version of the TomDoc specification can be found at: # # https://github.com/mojombo/tomdoc/blob/master/tomdoc.md # # To choose TomDoc as your only default format see RDoc::Options@Saved+Options # for instructions on setting up a .rdoc_options file to store # your project default. # # There are a few differences between this parser and the specification. A # best-effort was made to follow the specification as closely as possible but # some choices to deviate were made. # # A future version of RDoc will warn when a MUST or MUST NOT is violated and # may warn when a SHOULD or SHOULD NOT is violated. RDoc will always try # to emit documentation even if given invalid TomDoc. # # Here are some implementation choices this parser currently makes: # # This parser allows rdoc-style inline markup but you should not depended on # it. # # This parser allows a space between the comment and the method body. # # This parser does not require the default value to be described for an # optional argument. # # This parser does not examine the order of sections. An Examples section may # precede the Arguments section. # # This class is documented in TomDoc format. Since this is a subclass of the # RDoc markup parser there isn't much to see here, unfortunately. class RDoc::TomDoc < RDoc::Markup::Parser # Internal: Token accessor attr_reader :tokens # Internal: Adds a post-processor which sets the RDoc section based on the # comment's status. # # Returns nothing. def self.add_post_processor # :nodoc: RDoc::Markup::PreProcess.post_process do |comment, code_object| next unless code_object and RDoc::Comment === comment and comment.format == 'tomdoc' comment.text.gsub!(/(\A\s*# )(Public|Internal|Deprecated):\s+/) do section = code_object.add_section $2 code_object.temporary_section = section $1 end end end add_post_processor # Public: Parses TomDoc from text # # text - A String containing TomDoc-format text. # # Examples # # RDoc::TomDoc.parse <<-TOMDOC # This method does some things # # Returns nothing. # TOMDOC # # => # # # Returns an RDoc::Markup::Document representing the TomDoc format. def self.parse text parser = new parser.tokenize text doc = RDoc::Markup::Document.new parser.parse doc doc end # Internal: Extracts the Signature section's method signature # # comment - An RDoc::Comment that will be parsed and have the signature # extracted # # Returns a String containing the signature and nil if not def self.signature comment return unless comment.tomdoc? document = comment.parse signature = nil found_heading = false found_signature = false document.parts.delete_if do |part| next false if found_signature found_heading ||= RDoc::Markup::Heading === part && part.text == 'Signature' next false unless found_heading next true if RDoc::Markup::BlankLine === part if RDoc::Markup::Verbatim === part then signature = part found_signature = true end end signature and signature.text end # Public: Creates a new TomDoc parser. See also RDoc::Markup::parse def initialize super @section = nil end # Internal: Builds a heading from the token stream # # level - The level of heading to create # # Returns an RDoc::Markup::Heading def build_heading level heading = super @section = heading.text heading end # Internal: Builds a verbatim from the token stream. A verbatim in the # Examples section will be marked as in ruby format. # # margin - The indentation from the margin for lines that belong to this # verbatim section. # # Returns an RDoc::Markup::Verbatim def build_verbatim margin verbatim = super verbatim.format = :ruby if @section == 'Examples' verbatim end # Internal: Builds a paragraph from the token stream # # margin - Unused # # Returns an RDoc::Markup::Paragraph. def build_paragraph margin p :paragraph_start => margin if @debug paragraph = RDoc::Markup::Paragraph.new until @tokens.empty? do type, data, = get if type == :TEXT then paragraph << data skip :NEWLINE else unget break end end p :paragraph_end => margin if @debug paragraph end # Internal: Turns text into an Array of tokens # # text - A String containing TomDoc-format text. # # Returns self. def tokenize text text.sub!(/\A(Public|Internal|Deprecated):\s+/, '') setup_scanner text until @s.eos? do pos = @s.pos # leading spaces will be reflected by the column of the next token # the only thing we loose are trailing spaces at the end of the file next if @s.scan(/ +/) @tokens << case when @s.scan(/\r?\n/) then token = [:NEWLINE, @s.matched, *token_pos(pos)] @line_pos = char_pos @s.pos @line += 1 token when @s.scan(/(Examples|Signature)$/) then @tokens << [:HEADER, 3, *token_pos(pos)] [:TEXT, @s[1], *token_pos(pos)] when @s.scan(/([:\w][\w\[\]]*)[ ]+- /) then [:NOTE, @s[1], *token_pos(pos)] else @s.scan(/.*/) [:TEXT, @s.matched.sub(/\r$/, ''), *token_pos(pos)] end end self end end rdoc/alias.rb000064400000004137147635155430007133 0ustar00## # Represent an alias, which is an old_name/new_name pair associated with a # particular context #-- # TODO implement Alias as a proxy to a method/attribute, inheriting from # MethodAttr class RDoc::Alias < RDoc::CodeObject ## # Aliased method's name attr_reader :new_name alias name new_name ## # Aliasee method's name attr_reader :old_name ## # Is this an alias declared in a singleton context? attr_accessor :singleton ## # Source file token stream attr_reader :text ## # Creates a new Alias with a token stream of +text+ that aliases +old_name+ # to +new_name+, has +comment+ and is a +singleton+ context. def initialize(text, old_name, new_name, comment, singleton = false) super() @text = text @singleton = singleton @old_name = old_name @new_name = new_name self.comment = comment end ## # Order by #singleton then #new_name def <=>(other) [@singleton ? 0 : 1, new_name] <=> [other.singleton ? 0 : 1, other.new_name] end ## # HTML fragment reference for this alias def aref type = singleton ? 'c' : 'i' "#alias-#{type}-#{html_name}" end ## # Full old name including namespace def full_old_name @full_name || "#{parent.name}#{pretty_old_name}" end ## # HTML id-friendly version of +#new_name+. def html_name CGI.escape(@new_name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '') end def inspect # :nodoc: parent_name = parent ? parent.name : '(unknown)' "#<%s:0x%x %s.alias_method %s, %s>" % [ self.class, object_id, parent_name, @old_name, @new_name, ] end ## # '::' for the alias of a singleton method/attribute, '#' for instance-level. def name_prefix singleton ? '::' : '#' end ## # Old name with prefix '::' or '#'. def pretty_old_name "#{singleton ? '::' : '#'}#{@old_name}" end ## # New name with prefix '::' or '#'. def pretty_new_name "#{singleton ? '::' : '#'}#{@new_name}" end alias pretty_name pretty_new_name def to_s # :nodoc: "alias: #{self.new_name} -> #{self.pretty_old_name} in: #{parent}" end end rdoc/ruby_lex.rb000064400000066465147635155430007707 0ustar00# coding: US-ASCII #-- # irb/ruby-lex.rb - ruby lexcal analyzer # $Release Version: 0.9.5$ # $Revision: 17979 $ # $Date: 2008-07-09 10:17:05 -0700 (Wed, 09 Jul 2008) $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # #++ require "e2mmap" require "irb/slex" require "stringio" ## # Ruby lexer adapted from irb. # # The internals are not documented because they are scary. class RDoc::RubyLex ## # Raised upon invalid input class Error < RDoc::Error end # :stopdoc: extend Exception2MessageMapper def_exception(:AlreadyDefinedToken, "Already defined token(%s)") def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')") def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')") def_exception(:TkReading2TokenDuplicateError, "key duplicate(token_n='%s', key='%s')") def_exception(:SyntaxError, "%s") def_exception(:TerminateLineInput, "Terminate Line Input") include RDoc::RubyToken include IRB attr_reader :continue attr_reader :lex_state attr_reader :reader class << self attr_accessor :debug_level end def self.debug? @debug_level > 0 end self.debug_level = 0 # :startdoc: ## # Returns an Array of +ruby+ tokens. See ::new for a description of # +options+. def self.tokenize ruby, options tokens = [] scanner = RDoc::RubyLex.new ruby, options scanner.exception_on_syntax_error = true while token = scanner.token do tokens << token end tokens end ## # Creates a new lexer for +content+. +options+ is an RDoc::Options, only # +tab_width is used. def initialize(content, options) lex_init if /\t/ =~ content then tab_width = options.tab_width content = content.split(/\n/).map do |line| 1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width) } && $~ line end.join("\n") end content << "\n" unless content[-1, 1] == "\n" set_input StringIO.new content @base_char_no = 0 @char_no = 0 @exp_line_no = @line_no = 1 @here_readed = [] @readed = [] @rests = [] @seek = 0 @here_header = false @indent = 0 @indent_stack = [] @lex_state = EXPR_BEG @space_seen = false @continue = false @line = "" @skip_space = false @readed_auto_clean_up = false @exception_on_syntax_error = true @prompt = nil @prev_seek = nil @ltype = nil end # :stopdoc: def inspect # :nodoc: "#<%s:0x%x pos %d lex_state %p space_seen %p>" % [ self.class, object_id, @io.pos, @lex_state, @space_seen, ] end attr_accessor :skip_space attr_accessor :readed_auto_clean_up attr_accessor :exception_on_syntax_error attr_reader :seek attr_reader :char_no attr_reader :line_no attr_reader :indent # io functions def set_input(io, p = nil, &block) @io = io if p.respond_to?(:call) @input = p elsif block_given? @input = block else @input = Proc.new{@io.gets} end end def get_readed if idx = @readed.rindex("\n") @base_char_no = @readed.size - (idx + 1) else @base_char_no += @readed.size end readed = @readed.join("") @readed = [] readed end def getc while @rests.empty? # return nil unless buf_input @rests.push nil unless buf_input end c = @rests.shift if @here_header @here_readed.push c else @readed.push c end @seek += 1 if c == "\n" @line_no += 1 @char_no = 0 else @char_no += 1 end c end def gets l = "" while c = getc l.concat(c) break if c == "\n" end return nil if l == "" and c.nil? l end def eof? @io.eof? end def getc_of_rests if @rests.empty? nil else getc end end def ungetc(c = nil) if @here_readed.empty? c2 = @readed.pop else c2 = @here_readed.pop end c = c2 unless c @rests.unshift c #c = @seek -= 1 if c == "\n" @line_no -= 1 if idx = @readed.rindex("\n") @char_no = idx + 1 else @char_no = @base_char_no + @readed.size end else @char_no -= 1 end end def peek_equal?(str) chrs = str.split(//) until @rests.size >= chrs.size return false unless buf_input end @rests[0, chrs.size] == chrs end def peek_match?(regexp) while @rests.empty? return false unless buf_input end regexp =~ @rests.join("") end def peek(i = 0) while @rests.size <= i return nil unless buf_input end @rests[i] end def buf_input prompt line = @input.call return nil unless line @rests.concat line.split(//) true end private :buf_input def set_prompt(p = nil, &block) p = block if block_given? if p.respond_to?(:call) @prompt = p else @prompt = Proc.new{print p} end end def prompt if @prompt @prompt.call(@ltype, @indent, @continue, @line_no) end end def initialize_input @ltype = nil @quoted = nil @indent = 0 @indent_stack = [] @lex_state = EXPR_BEG @space_seen = false @here_header = false @continue = false prompt @line = "" @exp_line_no = @line_no end def each_top_level_statement initialize_input catch(:TERM_INPUT) do loop do begin @continue = false prompt unless l = lex throw :TERM_INPUT if @line == '' else #p l @line.concat l if @ltype or @continue or @indent > 0 next end end if @line != "\n" yield @line, @exp_line_no end break unless l @line = '' @exp_line_no = @line_no @indent = 0 @indent_stack = [] prompt rescue TerminateLineInput initialize_input prompt get_readed end end end end def lex until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) && !@continue or tk.nil?) #p tk #p @lex_state #p self end line = get_readed # print self.inspect if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil? nil else line end end def token # require "tracer" # Tracer.on @prev_seek = @seek @prev_line_no = @line_no @prev_char_no = @char_no begin begin tk = @OP.match(self) @space_seen = tk.kind_of?(TkSPACE) rescue SyntaxError => e raise Error, "syntax error: #{e.message}" if @exception_on_syntax_error tk = TkError.new(@seek, @line_no, @char_no) end end while @skip_space and tk.kind_of?(TkSPACE) if @readed_auto_clean_up get_readed end # Tracer.off tk end ENINDENT_CLAUSE = [ "case", "class", "def", "do", "for", "if", "module", "unless", "until", "while", "begin" #, "when" ] DEINDENT_CLAUSE = ["end" #, "when" ] PERCENT_LTYPE = { "q" => "\'", "Q" => "\"", "x" => "\`", "r" => "/", "w" => "]", "W" => "]", "s" => ":" } PERCENT_PAREN = { "{" => "}", "[" => "]", "<" => ">", "(" => ")" } PERCENT_PAREN_REV = PERCENT_PAREN.invert Ltype2Token = { "\'" => TkSTRING, "\"" => TkSTRING, "\`" => TkXSTRING, "/" => TkREGEXP, "]" => TkDSTRING, ":" => TkSYMBOL } DLtype2Token = { "\"" => TkDSTRING, "\`" => TkDXSTRING, "/" => TkDREGEXP, } def lex_init() @OP = IRB::SLex.new @OP.def_rules("\0", "\004", "\032") do |op, io| Token(TkEND_OF_SCRIPT, '') end @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |op, io| @space_seen = true str = op while (ch = getc) =~ /[ \t\f\r\13]/ do str << ch end ungetc Token TkSPACE, str end @OP.def_rule("#") do |op, io| identify_comment end @OP.def_rule("=begin", proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do |op, io| @ltype = "=" res = '' nil until (ch = getc) == "\n" until ( peek_equal?("=end") && peek(4) =~ /\s/ ) do (ch = getc) res << ch end gets # consume =end @ltype = nil Token(TkRD_COMMENT, res) end @OP.def_rule("\n") do |op, io| print "\\n\n" if RDoc::RubyLex.debug? case @lex_state when EXPR_BEG, EXPR_FNAME, EXPR_DOT @continue = true else @continue = false @lex_state = EXPR_BEG until (@indent_stack.empty? || [TkLPAREN, TkLBRACK, TkLBRACE, TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) @indent_stack.pop end end @here_header = false @here_readed = [] Token(TkNL) end @OP.def_rules("*", "**", "=", "==", "===", "=~", "<=>", "<", "<=", ">", ">=", ">>") do |op, io| case @lex_state when EXPR_FNAME, EXPR_DOT @lex_state = EXPR_ARG else @lex_state = EXPR_BEG end Token(op) end @OP.def_rules("!", "!=", "!~") do |op, io| @lex_state = EXPR_BEG Token(op) end @OP.def_rules("<<") do |op, io| tk = nil if @lex_state != EXPR_END && @lex_state != EXPR_CLASS && (@lex_state != EXPR_ARG || @space_seen) c = peek(0) if /\S/ =~ c && (/["'`]/ =~ c || /\w/ =~ c || c == "-") tk = identify_here_document end end unless tk tk = Token(op) case @lex_state when EXPR_FNAME, EXPR_DOT @lex_state = EXPR_ARG else @lex_state = EXPR_BEG end end tk end @OP.def_rules("'", '"') do |op, io| identify_string(op) end @OP.def_rules("`") do |op, io| if @lex_state == EXPR_FNAME @lex_state = EXPR_END Token(op) else identify_string(op) end end @OP.def_rules('?') do |op, io| if @lex_state == EXPR_END @lex_state = EXPR_BEG Token(TkQUESTION) else ch = getc if @lex_state == EXPR_ARG && ch =~ /\s/ ungetc @lex_state = EXPR_BEG; Token(TkQUESTION) else @lex_state = EXPR_END Token(TkSTRING, ch) end end end @OP.def_rules("&", "&&", "|", "||") do |op, io| @lex_state = EXPR_BEG Token(op) end @OP.def_rules("+=", "-=", "*=", "**=", "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do |op, io| @lex_state = EXPR_BEG op =~ /^(.*)=$/ Token(TkOPASGN, $1) end @OP.def_rule("+@", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token(op) end @OP.def_rule("-@", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token(op) end @OP.def_rules("+", "-") do |op, io| catch(:RET) do if @lex_state == EXPR_ARG if @space_seen and peek(0) =~ /[0-9]/ throw :RET, identify_number(op) else @lex_state = EXPR_BEG end elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/ throw :RET, identify_number(op) else @lex_state = EXPR_BEG end Token(op) end end @OP.def_rule(".") do |op, io| @lex_state = EXPR_BEG if peek(0) =~ /[0-9]/ ungetc identify_number else # for "obj.if" etc. @lex_state = EXPR_DOT Token(TkDOT) end end @OP.def_rules("..", "...") do |op, io| @lex_state = EXPR_BEG Token(op) end lex_int2 end def lex_int2 @OP.def_rules("]", "}", ")") do |op, io| @lex_state = EXPR_END @indent -= 1 @indent_stack.pop Token(op) end @OP.def_rule(":") do |op, io| if @lex_state == EXPR_END || peek(0) =~ /\s/ @lex_state = EXPR_BEG Token(TkCOLON) else @lex_state = EXPR_FNAME; Token(TkSYMBEG) end end @OP.def_rule("::") do |op, io| # p @lex_state.id2name, @space_seen if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen @lex_state = EXPR_BEG Token(TkCOLON3) else @lex_state = EXPR_DOT Token(TkCOLON2) end end @OP.def_rule("/") do |op, io| if @lex_state == EXPR_BEG || @lex_state == EXPR_MID identify_string(op) elsif peek(0) == '=' getc @lex_state = EXPR_BEG Token(TkOPASGN, "/") #/) elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/ identify_string(op) else @lex_state = EXPR_BEG Token("/") #/) end end @OP.def_rules("^") do |op, io| @lex_state = EXPR_BEG Token("^") end # @OP.def_rules("^=") do # @lex_state = EXPR_BEG # Token(OP_ASGN, :^) # end @OP.def_rules(",") do |op, io| @lex_state = EXPR_BEG Token(op) end @OP.def_rules(";") do |op, io| @lex_state = EXPR_BEG until (@indent_stack.empty? || [TkLPAREN, TkLBRACK, TkLBRACE, TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) @indent_stack.pop end Token(op) end @OP.def_rule("~") do |op, io| @lex_state = EXPR_BEG Token("~") end @OP.def_rule("~@", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_BEG Token("~") end @OP.def_rule("(") do |op, io| @indent += 1 if @lex_state == EXPR_BEG || @lex_state == EXPR_MID @lex_state = EXPR_BEG tk_c = TkfLPAREN else @lex_state = EXPR_BEG tk_c = TkLPAREN end @indent_stack.push tk_c Token tk_c end @OP.def_rule("[]", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token("[]") end @OP.def_rule("[]=", proc{|op, io| @lex_state == EXPR_FNAME}) do |op, io| @lex_state = EXPR_ARG Token("[]=") end @OP.def_rule("[") do |op, io| @indent += 1 if @lex_state == EXPR_FNAME tk_c = TkfLBRACK else if @lex_state == EXPR_BEG || @lex_state == EXPR_MID tk_c = TkLBRACK elsif @lex_state == EXPR_ARG && @space_seen tk_c = TkLBRACK else tk_c = TkfLBRACK end @lex_state = EXPR_BEG end @indent_stack.push tk_c Token(tk_c) end @OP.def_rule("{") do |op, io| @indent += 1 if @lex_state != EXPR_END && @lex_state != EXPR_ARG tk_c = TkLBRACE else tk_c = TkfLBRACE end @lex_state = EXPR_BEG @indent_stack.push tk_c Token(tk_c) end @OP.def_rule('\\') do |op, io| if getc == "\n" @space_seen = true @continue = true Token(TkSPACE) else ungetc Token("\\") end end @OP.def_rule('%') do |op, io| if @lex_state == EXPR_BEG || @lex_state == EXPR_MID identify_quotation elsif peek(0) == '=' getc Token(TkOPASGN, :%) elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/ identify_quotation else @lex_state = EXPR_BEG Token("%") #)) end end @OP.def_rule('$') do |op, io| identify_gvar end @OP.def_rule('@') do |op, io| if peek(0) =~ /[\w@]/ ungetc identify_identifier else Token("@") end end # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do # |op, io| # @indent += 1 # @lex_state = EXPR_FNAME # # @lex_state = EXPR_END # # until @rests[0] == "\n" or @rests[0] == ";" # # rests.shift # # end # end @OP.def_rule("_") do if peek_match?(/_END__/) and @lex_state == EXPR_BEG then 6.times { getc } Token(TkEND_OF_SCRIPT, '__END__') else ungetc identify_identifier end end @OP.def_rule("") do |op, io| printf "MATCH: start %s: %s\n", op, io.inspect if RDoc::RubyLex.debug? if peek(0) =~ /[0-9]/ t = identify_number else t = identify_identifier end printf "MATCH: end %s: %s\n", op, io.inspect if RDoc::RubyLex.debug? t end p @OP if RDoc::RubyLex.debug? end def identify_gvar @lex_state = EXPR_END case ch = getc when /[~_*$?!@\/\\;,=:<>".]/ #" Token(TkGVAR, "$" + ch) when "-" Token(TkGVAR, "$-" + getc) when "&", "`", "'", "+" Token(TkBACK_REF, "$"+ch) when /[1-9]/ ref = ch while (ch = getc) =~ /[0-9]/ do ref << ch end ungetc Token(TkNTH_REF, "$#{ref}") when /\w/ ungetc ungetc identify_identifier else ungetc Token("$") end end IDENT_RE = if defined? Encoding then eval '/[\w\u{0080}-\u{FFFFF}]/u' # 1.8 can't parse \u{} else /[\w\x80-\xFF]/ end def identify_identifier token = "" if peek(0) =~ /[$@]/ token.concat(c = getc) if c == "@" and peek(0) == "@" token.concat getc end end while (ch = getc) =~ IDENT_RE do print " :#{ch}: " if RDoc::RubyLex.debug? token.concat ch end ungetc if (ch == "!" || ch == "?") && token[0,1] =~ /\w/ && peek(0) != "=" token.concat getc end # almost fix token case token when /^\$/ return Token(TkGVAR, token) when /^\@\@/ @lex_state = EXPR_END # p Token(TkCVAR, token) return Token(TkCVAR, token) when /^\@/ @lex_state = EXPR_END return Token(TkIVAR, token) end if @lex_state != EXPR_DOT print token, "\n" if RDoc::RubyLex.debug? token_c, *trans = TkReading2Token[token] if token_c # reserved word? if (@lex_state != EXPR_BEG && @lex_state != EXPR_FNAME && trans[1]) # modifiers token_c = TkSymbol2Token[trans[1]] @lex_state = trans[0] else if @lex_state != EXPR_FNAME if ENINDENT_CLAUSE.include?(token) # check for ``class = val'' etc. valid = true case token when "class" valid = false unless peek_match?(/^\s*(<<|\w|::)/) when "def" valid = false if peek_match?(/^\s*(([+-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/) when "do" valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&)/) when *ENINDENT_CLAUSE valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&|\|)/) else # no nothing end if valid if token == "do" if ![TkFOR, TkWHILE, TkUNTIL].include?(@indent_stack.last) @indent += 1 @indent_stack.push token_c end else @indent += 1 @indent_stack.push token_c end else token_c = TkIDENTIFIER end elsif DEINDENT_CLAUSE.include?(token) @indent -= 1 @indent_stack.pop end @lex_state = trans[0] else @lex_state = EXPR_END end end return Token(token_c, token) end end if @lex_state == EXPR_FNAME @lex_state = EXPR_END if peek(0) == '=' token.concat getc end elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT || @lex_state == EXPR_ARG @lex_state = EXPR_ARG else @lex_state = EXPR_END end if token[0, 1] =~ /[A-Z]/ return Token(TkCONSTANT, token) elsif token[token.size - 1, 1] =~ /[!?]/ return Token(TkFID, token) else return Token(TkIDENTIFIER, token) end end def identify_here_document ch = getc # if lt = PERCENT_LTYPE[ch] if ch == "-" ch = getc indent = true end if /['"`]/ =~ ch user_quote = lt = ch quoted = "" while (c = getc) && c != lt quoted.concat c end else user_quote = nil lt = '"' quoted = ch.dup while (c = getc) && c =~ /\w/ quoted.concat c end ungetc end ltback, @ltype = @ltype, lt reserve = [] while ch = getc reserve.push ch if ch == "\\" reserve.push ch = getc elsif ch == "\n" break end end output_heredoc = reserve.join =~ /\A\r?\n\z/ if output_heredoc then doc = '<<' doc << '-' if indent doc << "#{user_quote}#{quoted}#{user_quote}\n" else doc = '"' end @here_header = false while l = gets l = l.sub(/(:?\r)?\n\z/, "\n") if (indent ? l.strip : l.chomp) == quoted break end doc << l end if output_heredoc then raise Error, "Missing terminating #{quoted} for string" unless l doc << l.chomp else doc << '"' end @here_header = true @here_readed.concat reserve while ch = reserve.pop ungetc ch end token_class = output_heredoc ? RDoc::RubyLex::TkHEREDOC : Ltype2Token[lt] @ltype = ltback @lex_state = EXPR_END Token(token_class, doc) end def identify_quotation type = ch = getc if lt = PERCENT_LTYPE[type] ch = getc elsif type =~ /\W/ type = nil lt = "\"" else return Token(TkMOD, '%') end # if ch !~ /\W/ # ungetc # next # end #@ltype = lt @quoted = ch unless @quoted = PERCENT_PAREN[ch] identify_string(lt, @quoted, type) end def identify_number(op = "") @lex_state = EXPR_END num = op if peek(0) == "0" && peek(1) !~ /[.eE]/ num << getc case peek(0) when /[xX]/ ch = getc match = /[0-9a-fA-F_]/ when /[bB]/ ch = getc match = /[01_]/ when /[oO]/ ch = getc match = /[0-7_]/ when /[dD]/ ch = getc match = /[0-9_]/ when /[0-7]/ match = /[0-7_]/ when /[89]/ raise Error, "Illegal octal digit" else return Token(TkINTEGER, num) end num << ch if ch len0 = true non_digit = false while ch = getc num << ch if match =~ ch if ch == "_" if non_digit raise Error, "trailing `#{ch}' in number" else non_digit = ch end else non_digit = false len0 = false end else ungetc num[-1, 1] = '' if len0 raise Error, "numeric literal without digits" end if non_digit raise Error, "trailing `#{non_digit}' in number" end break end end return Token(TkINTEGER, num) end type = TkINTEGER allow_point = true allow_e = true non_digit = false while ch = getc num << ch case ch when /[0-9]/ non_digit = false when "_" non_digit = ch when allow_point && "." if non_digit raise Error, "trailing `#{non_digit}' in number" end type = TkFLOAT if peek(0) !~ /[0-9]/ type = TkINTEGER ungetc num[-1, 1] = '' break end allow_point = false when allow_e && "e", allow_e && "E" if non_digit raise Error, "trailing `#{non_digit}' in number" end type = TkFLOAT if peek(0) =~ /[+-]/ num << getc end allow_e = false allow_point = false non_digit = ch else if non_digit raise Error, "trailing `#{non_digit}' in number" end ungetc num[-1, 1] = '' break end end Token(type, num) end def identify_string(ltype, quoted = ltype, type = nil) close = PERCENT_PAREN.values.include?(quoted) @ltype = ltype @quoted = quoted str = if ltype == quoted and %w[" ' /].include? ltype then ltype.dup elsif RUBY_VERSION > '1.9' then "%#{type or PERCENT_LTYPE.key ltype}#{PERCENT_PAREN_REV[quoted]}" else "%#{type or PERCENT_LTYPE.index ltype}#{PERCENT_PAREN_REV[quoted]}" end subtype = nil begin nest = 0 while ch = getc str << ch if @quoted == ch and nest <= 0 break elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#" ch = getc subtype = true if ch == "{" then str << ch << skip_inner_expression next else ungetc end elsif ch == '\\' if %w[' /].include? @ltype then case ch = getc when "\\", "\n", "'" when @ltype str << ch else ungetc end else str << read_escape end end if close then if PERCENT_PAREN[ch] == @quoted nest += 1 elsif ch == @quoted nest -= 1 end end end if @ltype == "/" if peek(0) =~ /i|m|x|o|e|s|u|n/ getc end end if subtype Token(DLtype2Token[ltype], str) else Token(Ltype2Token[ltype], str) end ensure @ltype = nil @quoted = nil @lex_state = EXPR_END end end def skip_inner_expression res = "" nest = 0 while ch = getc res << ch if ch == '}' break if nest.zero? nest -= 1 elsif ch == '{' nest += 1 end end res end def identify_comment @ltype = "#" comment = '#' while ch = getc # if ch == "\\" #" # read_escape # end if ch == "\n" @ltype = nil ungetc break end comment << ch end return Token(TkCOMMENT, comment) end def read_escape escape = '' ch = getc escape << ch case ch when "\n", "\r", "\f" when "\\", "n", "t", "r", "f", "v", "a", "e", "b", "s" #" when /[0-7]/ ungetc ch 3.times do ch = getc escape << ch case ch when /[0-7]/ when nil break else ungetc break end end when "x" 2.times do ch = getc escape << ch case ch when /[0-9a-fA-F]/ when nil break else ungetc break end end when "M" ch = getc escape << ch if ch != '-' ungetc else ch = getc escape << ch if ch == "\\" #" escape << read_escape end end when "C", "c" #, "^" if ch == "C" and (ch = getc) != "-" escape << ch ungetc elsif (ch = getc) == "\\" #" escape << ch << read_escape end else # other characters end escape end # :startdoc: end #RDoc::RubyLex.debug_level = 1 rdoc/generator/darkfish.rb000064400000045306147635155430011626 0ustar00# -*- mode: ruby; ruby-indent-level: 2; tab-width: 2 -*- require 'erb' require 'fileutils' require 'pathname' require 'rdoc/generator/markup' ## # Darkfish RDoc HTML Generator # # $Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $ # # == Author/s # * Michael Granger (ged@FaerieMUD.org) # # == Contributors # * Mahlon E. Smith (mahlon@martini.nu) # * Eric Hodel (drbrain@segment7.net) # # == License # # Copyright (c) 2007, 2008, Michael Granger. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the author/s, nor the names of the project's # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # == Attributions # # Darkfish uses the {Silk Icons}[http://www.famfamfam.com/lab/icons/silk/] set # by Mark James. class RDoc::Generator::Darkfish RDoc::RDoc.add_generator self include ERB::Util ## # Path to this file's parent directory. Used to find templates and other # resources. GENERATOR_DIR = File.join 'rdoc', 'generator' ## # Release Version VERSION = '3' ## # Description of this generator DESCRIPTION = 'HTML generator, written by Michael Granger' ## # The relative path to style sheets and javascript. By default this is set # the same as the rel_prefix. attr_accessor :asset_rel_path ## # The path to generate files into, combined with --op from the # options for a full path. attr_reader :base_dir ## # Classes and modules to be used by this generator, not necessarily # displayed. See also #modsort attr_reader :classes ## # No files will be written when dry_run is true. attr_accessor :dry_run ## # When false the generate methods return a String instead of writing to a # file. The default is true. attr_accessor :file_output ## # Files to be displayed by this generator attr_reader :files ## # The JSON index generator for this Darkfish generator attr_reader :json_index ## # Methods to be displayed by this generator attr_reader :methods ## # Sorted list of classes and modules to be displayed by this generator attr_reader :modsort ## # The RDoc::Store that is the source of the generated content attr_reader :store ## # The output directory attr_reader :outputdir ## # Initialize a few instance variables before we start def initialize store, options @store = store @options = options @asset_rel_path = '' @base_dir = Pathname.pwd.expand_path @dry_run = @options.dry_run @file_output = true @template_dir = Pathname.new options.template_dir @template_cache = {} @classes = nil @context = nil @files = nil @methods = nil @modsort = nil @json_index = RDoc::Generator::JsonIndex.new self, options end ## # Output progress information if debugging is enabled def debug_msg *msg return unless $DEBUG_RDOC $stderr.puts(*msg) end ## # Directory where generated class HTML files live relative to the output # dir. def class_dir nil end ## # Directory where generated class HTML files live relative to the output # dir. def file_dir nil end ## # Create the directories the generated docs will live in if they don't # already exist. def gen_sub_directories @outputdir.mkpath end ## # Copy over the stylesheet into the appropriate place in the output # directory. def write_style_sheet debug_msg "Copying static files" options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } FileUtils.cp @template_dir + 'rdoc.css', '.', options Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path| next if File.directory? path next if File.basename(path) =~ /^\./ dst = Pathname.new(path).relative_path_from @template_dir # I suck at glob dst_dir = dst.dirname FileUtils.mkdir_p dst_dir, options unless File.exist? dst_dir FileUtils.cp @template_dir + path, dst, options end end ## # Build the initial indices and output objects based on an array of TopLevel # objects containing the extracted information. def generate setup write_style_sheet generate_index generate_class_files generate_file_files generate_table_of_contents @json_index.generate copy_static rescue => e debug_msg "%s: %s\n %s" % [ e.class.name, e.message, e.backtrace.join("\n ") ] raise end ## # Copies static files from the static_path into the output directory def copy_static return if @options.static_path.empty? fu_options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } @options.static_path.each do |path| unless File.directory? path then FileUtils.install path, @outputdir, fu_options.merge(:mode => 0644) next end Dir.chdir path do Dir[File.join('**', '*')].each do |entry| dest_file = @outputdir + entry if File.directory? entry then FileUtils.mkdir_p entry, fu_options else FileUtils.install entry, dest_file, fu_options.merge(:mode => 0644) end end end end end ## # Return a list of the documented modules sorted by salience first, then # by name. def get_sorted_module_list classes classes.select do |klass| klass.display? end.sort end ## # Generate an index page which lists all the classes which are documented. def generate_index setup template_file = @template_dir + 'index.rhtml' return unless template_file.exist? debug_msg "Rendering the index page..." out_file = @base_dir + @options.op_dir + 'index.html' rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path @title = @options.title render_template template_file, out_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating index.html: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generates a class file for +klass+ def generate_class klass, template_file = nil setup current = klass template_file ||= @template_dir + 'class.rhtml' debug_msg " working on %s (%s)" % [klass.full_name, klass.path] out_file = @outputdir + klass.path rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path svninfo = svninfo = get_svninfo(current) @title = "#{klass.type} #{klass.full_name} - #{@options.title}" debug_msg " rendering #{out_file}" render_template template_file, out_file do |io| binding end end ## # Generate a documentation file for each class and module def generate_class_files setup template_file = @template_dir + 'class.rhtml' template_file = @template_dir + 'classpage.rhtml' unless template_file.exist? return unless template_file.exist? debug_msg "Generating class documentation in #{@outputdir}" current = nil @classes.each do |klass| current = klass generate_class klass, template_file end rescue => e error = RDoc::Error.new \ "error generating #{current.path}: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generate a documentation file for each file def generate_file_files setup page_file = @template_dir + 'page.rhtml' fileinfo_file = @template_dir + 'fileinfo.rhtml' # for legacy templates filepage_file = @template_dir + 'filepage.rhtml' unless page_file.exist? or fileinfo_file.exist? return unless page_file.exist? or fileinfo_file.exist? or filepage_file.exist? debug_msg "Generating file documentation in #{@outputdir}" out_file = nil current = nil @files.each do |file| current = file if file.text? and page_file.exist? then generate_page file next end template_file = nil out_file = @outputdir + file.path debug_msg " working on %s (%s)" % [file.full_name, out_file] rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path unless filepage_file then if file.text? then next unless page_file.exist? template_file = page_file @title = file.page_name else next unless fileinfo_file.exist? template_file = fileinfo_file @title = "File: #{file.base_name}" end end @title += " - #{@options.title}" template_file ||= filepage_file render_template template_file, out_file do |io| binding end end rescue => e error = RDoc::Error.new "error generating #{out_file}: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generate a page file for +file+ def generate_page file setup template_file = @template_dir + 'page.rhtml' out_file = @outputdir + file.path debug_msg " working on %s (%s)" % [file.full_name, out_file] rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning current = current = file asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path @title = "#{file.page_name} - #{@options.title}" debug_msg " rendering #{out_file}" render_template template_file, out_file do |io| binding end end ## # Generates the 404 page for the RDoc servlet def generate_servlet_not_found path setup template_file = @template_dir + 'servlet_not_found.rhtml' return unless template_file.exist? debug_msg "Rendering the servlet 404 Not Found page..." rel_prefix = rel_prefix = '' search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = '' @title = 'Not Found' render_template template_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating servlet_not_found: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generates the servlet root page for the RDoc servlet def generate_servlet_root installed setup template_file = @template_dir + 'servlet_root.rhtml' return unless template_file.exist? debug_msg 'Rendering the servlet root page...' rel_prefix = '.' asset_rel_prefix = rel_prefix search_index_rel_prefix = asset_rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output @title = 'Local RDoc Documentation' render_template template_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating servlet_root: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Generate an index page which lists all the classes which are documented. def generate_table_of_contents setup template_file = @template_dir + 'table_of_contents.rhtml' return unless template_file.exist? debug_msg "Rendering the Table of Contents..." out_file = @outputdir + 'table_of_contents.html' rel_prefix = @outputdir.relative_path_from out_file.dirname search_index_rel_prefix = rel_prefix search_index_rel_prefix += @asset_rel_path if @file_output # suppress 1.9.3 warning asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path @title = "Table of Contents - #{@options.title}" render_template template_file, out_file do |io| binding end rescue => e error = RDoc::Error.new \ "error generating table_of_contents.html: #{e.message} (#{e.class})" error.set_backtrace e.backtrace raise error end ## # Prepares for generation of output from the current directory def setup return if instance_variable_defined? :@outputdir @outputdir = Pathname.new(@options.op_dir).expand_path @base_dir return unless @store @classes = @store.all_classes_and_modules.sort @files = @store.all_files.sort @methods = @classes.map { |m| m.method_list }.flatten.sort @modsort = get_sorted_module_list @classes end ## # Return a string describing the amount of time in the given number of # seconds in terms a human can understand easily. def time_delta_string seconds return 'less than a minute' if seconds < 60 return "#{seconds / 60} minute#{seconds / 60 == 1 ? '' : 's'}" if seconds < 3000 # 50 minutes return 'about one hour' if seconds < 5400 # 90 minutes return "#{seconds / 3600} hours" if seconds < 64800 # 18 hours return 'one day' if seconds < 86400 # 1 day return 'about one day' if seconds < 172800 # 2 days return "#{seconds / 86400} days" if seconds < 604800 # 1 week return 'about one week' if seconds < 1209600 # 2 week return "#{seconds / 604800} weeks" if seconds < 7257600 # 3 months return "#{seconds / 2419200} months" if seconds < 31536000 # 1 year return "#{seconds / 31536000} years" end # %q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $" SVNID_PATTERN = / \$Id:\s (\S+)\s # filename (\d+)\s # rev (\d{4}-\d{2}-\d{2})\s # Date (YYYY-MM-DD) (\d{2}:\d{2}:\d{2}Z)\s # Time (HH:MM:SSZ) (\w+)\s # committer \$$ /x ## # Try to extract Subversion information out of the first constant whose # value looks like a subversion Id tag. If no matching constant is found, # and empty hash is returned. def get_svninfo klass constants = klass.constants or return {} constants.find { |c| c.value =~ SVNID_PATTERN } or return {} filename, rev, date, time, committer = $~.captures commitdate = Time.parse "#{date} #{time}" return { :filename => filename, :rev => Integer(rev), :commitdate => commitdate, :commitdelta => time_delta_string(Time.now - commitdate), :committer => committer, } end ## # Creates a template from its components and the +body_file+. # # For backwards compatibility, if +body_file+ contains " #{head_file.read} #{body} #{footer_file.read} TEMPLATE end ## # Renders the ERb contained in +file_name+ relative to the template # directory and returns the result based on the current context. def render file_name template_file = @template_dir + file_name template = template_for template_file, false, RDoc::ERBPartial template.filename = template_file.to_s template.result @context end ## # Load and render the erb template in the given +template_file+ and write # it out to +out_file+. # # Both +template_file+ and +out_file+ should be Pathname-like objects. # # An io will be yielded which must be captured by binding in the caller. def render_template template_file, out_file = nil # :yield: io io_output = out_file && !@dry_run && @file_output erb_klass = io_output ? RDoc::ERBIO : ERB template = template_for template_file, true, erb_klass if io_output then debug_msg "Outputting to %s" % [out_file.expand_path] out_file.dirname.mkpath out_file.open 'w', 0644 do |io| io.set_encoding @options.encoding if Object.const_defined? :Encoding @context = yield io template_result template, @context, template_file end else @context = yield nil output = template_result template, @context, template_file debug_msg " would have written %d characters to %s" % [ output.length, out_file.expand_path ] if @dry_run output end end ## # Creates the result for +template+ with +context+. If an error is raised a # Pathname +template_file+ will indicate the file where the error occurred. def template_result template, context, template_file template.filename = template_file.to_s template.result context rescue NoMethodError => e raise RDoc::Error, "Error while evaluating %s: %s" % [ template_file.expand_path, e.message, ], e.backtrace end ## # Retrieves a cache template for +file+, if present, or fills the cache. def template_for file, page = true, klass = ERB template = @template_cache[file] return template if template if page then template = assemble_template file erbout = 'io' else template = file.read template = template.encode @options.encoding if Object.const_defined? :Encoding file_var = File.basename(file).sub(/\..*/, '') erbout = "_erbout_#{file_var}" end template = klass.new template, nil, '<>', erbout @template_cache[file] = template template end end rdoc/generator/ri.rb000064400000000662147635155430010441 0ustar00## # Generates ri data files class RDoc::Generator::RI RDoc::RDoc.add_generator self ## # Description of this generator DESCRIPTION = 'creates ri data files' ## # Set up a new ri generator def initialize store, options #:not-new: @options = options @store = store @store.path = '.' end ## # Writes the parsed data store to disk for use by ri. def generate @store.save end end rdoc/generator/json_index.rb000064400000014326147635155430012171 0ustar00require 'json' ## # The JsonIndex generator is designed to complement an HTML generator and # produces a JSON search index. This generator is derived from sdoc by # Vladimir Kolesnikov and contains verbatim code written by him. # # This generator is designed to be used with a regular HTML generator: # # class RDoc::Generator::Darkfish # def initialize options # # ... # @base_dir = Pathname.pwd.expand_path # # @json_index = RDoc::Generator::JsonIndex.new self, options # end # # def generate # # ... # @json_index.generate # end # end # # == Index Format # # The index is output as a JSON file assigned to the global variable # +search_data+. The structure is: # # var search_data = { # "index": { # "searchIndex": # ["a", "b", ...], # "longSearchIndex": # ["a", "a::b", ...], # "info": [ # ["A", "A", "A.html", "", ""], # ["B", "A::B", "A::B.html", "", ""], # ... # ] # } # } # # The same item is described across the +searchIndex+, +longSearchIndex+ and # +info+ fields. The +searchIndex+ field contains the item's short name, the # +longSearchIndex+ field contains the full_name (when appropriate) and the # +info+ field contains the item's name, full_name, path, parameters and a # snippet of the item's comment. # # == LICENSE # # Copyright (c) 2009 Vladimir Kolesnikov # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class RDoc::Generator::JsonIndex include RDoc::Text ## # Where the search index lives in the generated output SEARCH_INDEX_FILE = File.join 'js', 'search_index.js' attr_reader :index # :nodoc: ## # Creates a new generator. +parent_generator+ is used to determine the # class_dir and file_dir of links in the output index. # # +options+ are the same options passed to the parent generator. def initialize parent_generator, options @parent_generator = parent_generator @store = parent_generator.store @options = options @template_dir = File.expand_path '../template/json_index', __FILE__ @base_dir = @parent_generator.base_dir @classes = nil @files = nil @index = nil end ## # Builds the JSON index as a Hash. def build_index reset @store.all_files.sort, @store.all_classes_and_modules.sort index_classes index_methods index_pages { :index => @index } end ## # Output progress information if debugging is enabled def debug_msg *msg return unless $DEBUG_RDOC $stderr.puts(*msg) end ## # Writes the JSON index to disk def generate debug_msg "Generating JSON index" debug_msg " writing search index to %s" % SEARCH_INDEX_FILE data = build_index return if @options.dry_run out_dir = @base_dir + @options.op_dir index_file = out_dir + SEARCH_INDEX_FILE FileUtils.mkdir_p index_file.dirname, :verbose => $DEBUG_RDOC index_file.open 'w', 0644 do |io| io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding io.write 'var search_data = ' JSON.dump data, io, 0 end Dir.chdir @template_dir do Dir['**/*.js'].each do |source| dest = File.join out_dir, source FileUtils.install source, dest, :mode => 0644, :verbose => $DEBUG_RDOC end end end ## # Adds classes and modules to the index def index_classes debug_msg " generating class search index" documented = @classes.uniq.select do |klass| klass.document_self_or_methods end documented.each do |klass| debug_msg " #{klass.full_name}" record = klass.search_record @index[:searchIndex] << search_string(record.shift) @index[:longSearchIndex] << search_string(record.shift) @index[:info] << record end end ## # Adds methods to the index def index_methods debug_msg " generating method search index" list = @classes.uniq.map do |klass| klass.method_list end.flatten.sort_by do |method| [method.name, method.parent.full_name] end list.each do |method| debug_msg " #{method.full_name}" record = method.search_record @index[:searchIndex] << "#{search_string record.shift}()" @index[:longSearchIndex] << "#{search_string record.shift}()" @index[:info] << record end end ## # Adds pages to the index def index_pages debug_msg " generating pages search index" pages = @files.select do |file| file.text? end pages.each do |page| debug_msg " #{page.page_name}" record = page.search_record @index[:searchIndex] << search_string(record.shift) @index[:longSearchIndex] << '' record.shift @index[:info] << record end end ## # The directory classes are written to def class_dir @parent_generator.class_dir end ## # The directory files are written to def file_dir @parent_generator.file_dir end def reset files, classes # :nodoc: @files = files @classes = classes @index = { :searchIndex => [], :longSearchIndex => [], :info => [] } end ## # Removes whitespace and downcases +string+ def search_string string string.downcase.gsub(/\s/, '') end end rdoc/generator/template/darkfish/js/search.js000064400000004502147635155430015324 0ustar00Search = function(data, input, result) { this.data = data; this.$input = $(input); this.$result = $(result); this.$current = null; this.$view = this.$result.parent(); this.searcher = new Searcher(data.index); this.init(); } Search.prototype = $.extend({}, Navigation, new function() { var suid = 1; this.init = function() { var _this = this; var observer = function() { _this.search(_this.$input[0].value); }; this.$input.keyup(observer); this.$input.click(observer); // mac's clear field this.searcher.ready(function(results, isLast) { _this.addResults(results, isLast); }) this.initNavigation(); this.setNavigationActive(false); } this.search = function(value, selectFirstMatch) { value = jQuery.trim(value).toLowerCase(); if (value) { this.setNavigationActive(true); } else { this.setNavigationActive(false); } if (value == '') { this.lastQuery = value; this.$result.empty(); this.setNavigationActive(false); } else if (value != this.lastQuery) { this.lastQuery = value; this.firstRun = true; this.searcher.find(value); } } this.addResults = function(results, isLast) { var target = this.$result.get(0); if (this.firstRun && (results.length > 0 || isLast)) { this.$current = null; this.$result.empty(); } for (var i=0, l = results.length; i < l; i++) { target.appendChild(this.renderItem.call(this, results[i])); }; if (this.firstRun && results.length > 0) { this.firstRun = false; this.$current = $(target.firstChild); this.$current.addClass('current'); } if (jQuery.browser.msie) this.$element[0].className += ''; } this.move = function(isDown) { if (!this.$current) return; var $next = this.$current[isDown ? 'next' : 'prev'](); if ($next.length) { this.$current.removeClass('current'); $next.addClass('current'); this.scrollIntoView($next[0], this.$view[0]); this.$current = $next; } return true; } this.hlt = function(html) { return this.escapeHTML(html). replace(/\u0001/g, ''). replace(/\u0002/g, ''); } this.escapeHTML = function(html) { return html.replace(/[&<>]/g, function(c) { return '&#' + c.charCodeAt(0) + ';'; }); } }); rdoc/generator/template/darkfish/js/darkfish.js000064400000010032147635155430015645 0ustar00/** * * Darkfish Page Functions * $Id: darkfish.js 53 2009-01-07 02:52:03Z deveiant $ * * Author: Michael Granger * */ /* Provide console simulation for firebug-less environments */ if (!("console" in window) || !("firebug" in console)) { var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {}; }; /** * Unwrap the first element that matches the given @expr@ from the targets and return them. */ $.fn.unwrap = function( expr ) { return this.each( function() { $(this).parents( expr ).eq( 0 ).after( this ).remove(); }); }; function showSource( e ) { var target = e.target; var codeSections = $(target). parents('.method-detail'). find('.method-source-code'); $(target). parents('.method-detail'). find('.method-source-code'). slideToggle(); }; function hookSourceViews() { $('.method-heading').click( showSource ); }; function toggleDebuggingSection() { $('.debugging-section').slideToggle(); }; function hookDebuggingToggle() { $('#debugging-toggle img').click( toggleDebuggingSection ); }; function hookTableOfContentsToggle() { $('.indexpage li .toc-toggle').each( function() { $(this).click( function() { $(this).toggleClass('open'); }); var section = $(this).next(); $(this).click( function() { section.slideToggle(); }); }); } function hookSearch() { var input = $('#search-field').eq(0); var result = $('#search-results').eq(0); $(result).show(); var search_section = $('#search-section').get(0); $(search_section).show(); var search = new Search(search_data, input, result); search.renderItem = function(result) { var li = document.createElement('li'); var html = ''; // TODO add relative path to rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml000064400000000710147635155430017450 0ustar00<% if !svninfo.empty? then %> <% end %> rdoc/generator/template/darkfish/rdoc.css000064400000024175147635155430014556 0ustar00/* * "Darkfish" Rdoc CSS * $Id: rdoc.css 54 2009-01-27 01:09:48Z deveiant $ * * Author: Michael Granger * */ /* vim: ft=css et sw=2 ts=2 sts=2 */ /* Base Green is: #6C8C22 */ * { padding: 0; margin: 0; } body { background: #efefef; font: 14px "Helvetica Neue", Helvetica, Tahoma, sans-serif; margin-left: 40px; } body.file-popup { font-size: 90%; margin-left: 0; } h1 { font-size: 300%; text-shadow: rgba(135,145,135,0.65) 2px 2px 3px; color: #6C8C22; } h2,h3,h4 { margin-top: 1.5em; } h1 span, h2 span, h3 span, h4 span, h5 span, h6 span { display: none; padding-left: 1em; font-size: 50%; vertical-align: super; } h1:hover span, h2:hover span, h3:hover span, h4:hover span, h5:hover span, h6:hover span { display: inline; } :link, :visited { color: #6C8C22; text-decoration: none; } :link:hover, :visited:hover { border-bottom: 1px dotted #6C8C22; } pre { background: #ddd; padding: 0.5em 0; } blockquote { background: #ddd; margin: 1em; padding: 0.25em; } blockquote > :first-child { margin-top: 0 !important; } /* @group Generic Classes */ .initially-hidden { display: none; } #search-field { width: 98%; background: #eee; border: none; height: 1.5em; -webkit-border-radius: 4px; } #search-field:focus { background: #f1edba; } #search-field:-moz-placeholder, #search-field::-webkit-input-placeholder { font-weight: bold; color: #666; } .missing-docs { font-size: 120%; background: white url(images/wrench_orange.png) no-repeat 4px center; color: #ccc; line-height: 2em; border: 1px solid #d00; opacity: 1; padding-left: 20px; text-indent: 24px; letter-spacing: 3px; font-weight: bold; -webkit-border-radius: 5px; -moz-border-radius: 5px; } .target-section { border: 2px solid #dcce90; border-left-width: 8px; padding: 0 1em; background: #fff3c2; } /* @end */ /* @group Index Page, Standalone file pages */ .indexpage ul { line-height: 160%; list-style: none; } .indexpage ul :link, .indexpage ul :visited { font-size: 16px; } .indexpage li { padding-left: 20px; } .indexpage ul > li { background: url(images/bullet_black.png) no-repeat left 4px; } .indexpage li.method { background: url(images/plugin.png) no-repeat left 4px; } .indexpage li.module { background: url(images/package.png) no-repeat left 4px; } .indexpage li.class { background: url(images/ruby.png) no-repeat left 4px; } .indexpage li.file { background: url(images/page_white_text.png) no-repeat left 4px; } .indexpage li li { background: url(images/tag_blue.png) no-repeat left 4px; } .indexpage li .toc-toggle { width: 16px; height: 16px; background: url(images/add.png) no-repeat; } .indexpage li .toc-toggle.open { background: url(images/delete.png) no-repeat; } /* @end */ /* @group Top-Level Structure */ #metadata { float: left; width: 260px; } #documentation { margin: 2em 1em 5em 300px; min-width: 340px; } #validator-badges { clear: both; margin: 1em 1em 2em; font-size: smaller; } /* @end */ /* @group Metadata Section */ #metadata .section { background-color: #dedede; -moz-border-radius: 5px; -webkit-border-radius: 5px; border: 1px solid #aaa; margin: 0 8px 8px; font-size: 90%; overflow: hidden; } #metadata h3.section-header { margin: 0; padding: 2px 8px; background: #ccc; color: #666; -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-left-radius: 4px; -webkit-border-top-right-radius: 4px; border-bottom: 1px solid #aaa; } #metadata #home-section h3.section-header { border-bottom: 0; } #metadata ul, #metadata dl, #metadata p { padding: 8px; list-style: none; } #file-metadata { margin-top: 2em; } #file-metadata ul { padding-left: 28px; list-style-image: url(images/page_green.png); } #table-of-contents { margin-top: 2em; } #table-of-contents ul { padding-left: 28px; list-style-image: url(images/tag_blue.png); } dl.svninfo { color: #666; margin: 0; } dl.svninfo dt { font-weight: bold; } ul.link-list li { white-space: nowrap; line-height: 20px; } ul.link-list .type { font-size: 8px; text-transform: uppercase; color: white; background: #969696; padding: 2px 4px; -webkit-border-radius: 5px; } .calls-super { background: url(images/arrow_up.png) no-repeat right center; } /* @end */ /* @group Class Metadata Section */ #class-metadata { margin-top: 2em; } /* @end */ /* @group Project Metadata Section */ #project-metadata { margin-top: 2em; } #project-metadata .section { border: 1px solid #aaa; } #project-metadata h3.section-header { border-bottom: 1px solid #aaa; position: relative; } #project-metadata form { color: #777; background: #ccc; } /* @end */ /* @group Documentation Section */ .description { font-size: 100%; color: #333; } .description p { margin: 1em 0.4em; } .description li p { margin: 0; } .description ol, .description ul { margin-left: 1.5em; } .description ol li, .description ul li { line-height: 1.4em; } .note-list { margin: 8px 0; } .label-list { margin: 8px 1.5em; border: 1px solid #ccc; } .description .label-list { font-size: 14px; } .note-list dt { font-weight: bold; } .note-list dd { padding: 0 12px; } .label-list dt { padding: 2px 4px; font-weight: bold; background: #ddd; } .label-list dd { padding: 2px 12px; } .label-list dd + dt, .note-list dd + dt { margin-top: 0.7em; } #documentation .section { font-size: 90%; } #documentation h2.section-header { margin-top: 1em; padding: 0.25em 0.5em; background: #ccc; color: #333; font-size: 175%; border: 1px solid #bbb; -moz-border-radius: 3px; -webkit-border-radius: 3px; } .documentation-section-title { position: relative; } .documentation-section-title .section-click-top { position: absolute; top: 6px; right: 12px; font-size: 10px; color: #9b9877; visibility: hidden; padding-right: 0.5px; } .documentation-section-title:hover .section-click-top { visibility: visible; } #documentation h3.section-header { margin-top: 1em; padding: 0.25em 0.5em; background-color: #dedede; color: #333; font-size: 150%; border: 1px solid #bbb; -moz-border-radius: 3px; -webkit-border-radius: 3px; } #constants-list > dl, #attributes-list > dl { margin: 1em 0 2em; border: 0; } #constants-list > dl dt, #attributes-list > dl dt { padding-left: 0; font-weight: bold; font-family: Monaco, "Andale Mono"; background: inherit; } #constants-list > dl dt a, #attributes-list > dl dt a { color: inherit; } #constants-list > dl dd, #attributes-list > dl dd { margin: 0 0 1em 0; padding: 0; color: #666; } .documentation-section h2 { position: relative; } .documentation-section h2 a { position: absolute; top: 8px; right: 10px; font-size: 12px; color: #9b9877; visibility: hidden; } .documentation-section h2:hover a { visibility: visible; } /* @group Method Details */ #documentation .method-source-code { display: none; } #documentation .method-description .method-calls-super { color: #333; font-weight: bolder; } #documentation .method-detail { margin: 0.5em 0; padding: 0.5em 0; cursor: pointer; } #documentation .method-detail:hover { background-color: #f1edba; } #documentation .method-heading { position: relative; padding: 2px 4px 0 20px; font-size: 125%; font-weight: bold; color: #333; background: url(images/brick.png) no-repeat left bottom; } #documentation .method-heading :link, #documentation .method-heading :visited { color: inherit; } #documentation .method-click-advice { position: absolute; top: 2px; right: 5px; font-size: 10px; color: #9b9877; visibility: hidden; padding-right: 20px; line-height: 20px; background: url(images/zoom.png) no-repeat right top; } #documentation .method-heading:hover .method-click-advice { visibility: visible; } #documentation .method-alias .method-heading { color: #666; background: url(images/brick_link.png) no-repeat left bottom; } #documentation .method-description, #documentation .aliases { margin: 0 20px; color: #666; } #documentation .method-description p, #documentation .aliases p { line-height: 1.2em; } #documentation .aliases { padding-top: 4px; font-style: italic; cursor: default; } #documentation .method-description p { margin-bottom: 0.5em; } #documentation .method-description ul { margin-left: 1.5em; } pre { margin: 0.5em 0; } #documentation .attribute-method-heading { background: url(images/tag_green.png) no-repeat left bottom; } #documentation #attribute-method-details .method-detail:hover { background-color: transparent; cursor: default; } #documentation .attribute-access-type { font-size: 60%; text-transform: uppercase; vertical-align: super; padding: 0 2px; } /* @end */ /* @end */ /* @group Source Code */ pre { overflow: auto; background: #262626; color: white; border: 1px dashed #999; padding: 0.5em; } .description pre { margin: 0 0.4em; } .ruby-constant { color: #7fffd4; background: transparent; } .ruby-keyword { color: #00ffff; background: transparent; } .ruby-ivar { color: #eedd82; background: transparent; } .ruby-operator { color: #00ffee; background: transparent; } .ruby-identifier { color: #ffdead; background: transparent; } .ruby-node { color: #ffa07a; background: transparent; } .ruby-comment { color: #dc0000; font-weight: bold; background: transparent; } .ruby-regexp { color: #ffa07a; background: transparent; } .ruby-value { color: #7fffd4; background: transparent; } /* @end */ /* @group search results */ #search-results h1 { font-size: 1em; font-weight: normal; text-shadow: none; } #search-results .current { background: #ccc; border-bottom: 1px solid transparent; } #search-results li { list-style: none; border-bottom: 1px solid #aaa; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; margin-bottom: 0.5em; } #search-results li:last-child { border-bottom: none; margin-bottom: 0; } #search-results li p { padding: 0; margin: 0.5em; } #search-results .search-namespace { font-weight: bold; } #search-results li em { background: yellow; font-style: normal; } #search-results pre { margin: 0.5em; } /* @end */ rdoc/generator/template/darkfish/_sidebar_installed.rhtml000064400000000472147635155430017766 0ustar00 rdoc/generator/template/darkfish/_sidebar_navigation.rhtml000064400000000437147635155430020147 0ustar00 rdoc/generator/template/darkfish/class.rhtml000064400000013633147635155430015267 0ustar00

    <%= klass.type %> <%= klass.full_name %>

    <%= klass.description %>
    <% klass.each_section do |section, constants, attributes| %> <% constants = constants.select { |const| const.display? } %> <% attributes = attributes.select { |attr| attr.display? } %>
    <% if section.title then %>

    <%= section.title %>

    ↑ top
    <% end %> <% if section.comment then %>
    <%= section.description %>
    <% end %> <% unless constants.empty? then %>

    Constants

    <% constants.each do |const| %>
    <%= const.name %> <% if const.comment then %>
    <%= const.description.strip %> <% else %>
    (Not documented) <% end %> <% end %>
    <% end %> <% unless attributes.empty? then %>

    Attributes

    <% attributes.each do |attrib| %>
    <%= h attrib.name %>[<%= attrib.rw %>]
    <% if attrib.comment then %> <%= attrib.description.strip %> <% else %>

    (Not documented) <% end %>

    <% end %>
    <% end %> <% klass.methods_by_type(section).each do |type, visibilities| next if visibilities.empty? visibilities.each do |visibility, methods| next if methods.empty? %>

    <%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods

    <% methods.each do |method| %>
    "> <% if method.call_seq then %> <% method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %>
    <%= h(call_seq.strip. gsub( /^\w+\./m, '')). gsub(/(.*)[-=]>/, '\1→') %> <% if i == 0 and method.token_stream then %> click to toggle source <% end %>
    <% end %> <% else %>
    <%= h method.name %><%= method.param_seq %> <% if method.token_stream then %> click to toggle source <% end %>
    <% end %>
    <% if method.comment then %> <%= method.description.strip %> <% else %>

    (Not documented) <% end %> <% if method.calls_super then %>

    Calls superclass method <%= method.superclass_method ? method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil %>
    <% end %> <% if method.token_stream then %>
    <%= method.markup_code %>
    <% end %>
    <% unless method.aliases.empty? then %>
    Also aliased as: <%= method.aliases.map do |aka| if aka.parent then # HACK lib/rexml/encodings %{#{h aka.name}} else h aka.name end end.join ", " %>
    <% end %> <% if method.is_alias_for then %> <% end %>
    <% end %>
    <% end end %>
    <% end %>
    rdoc/generator/template/darkfish/_sidebar_methods.rhtml000064400000000630147635155430017446 0ustar00<% unless klass.method_list.empty? then %> <% end %> rdoc/generator/template/darkfish/servlet_not_found.rhtml000064400000000563147635155430017717 0ustar00

    Not Found

    The page <%=h path %> was not found

    rdoc/generator/template/darkfish/images/package.png000064400000001525147635155430016455 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8}Kh\u{g̝4L)B1>n\F)PAD QTWf!"؍` HC0ijC1ͳLfw(v!g}69)wyc/T4"Գ X8ѫ̛vכ*WGU}[E>7&tJiG+*rQE>{ `=9o/rorgaw=MЪUQVcƏ;}ź;qD>r 7jT1aU&m86l7KVio{Ǥ9sVԨ,O"aWūmptk.h-V}֯K*R\M- Юޡ'O'CU0)79Ms&3P#V 'w'ů N,op#LRi4Qj h]GS\;QƤBH`1@<Ѐd^{9] !"dlǁD @|0mp  Q a+kK7 "$ h$?$BrN#&Cif N7SV[6laL/HbF6tX=ֽɕد}GO|뻗zUC5rh8D>)4Vwͦ|"L\>2FΫ[^yjW?'q{gBio.ȧTctܲ^&IENDB`rdoc/generator/template/darkfish/images/page_white_text.png000064400000000526147635155430020242 0ustar00PNG  IHDR7gAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT1nSAǞ4A(ISp.KPp"QA7%1Ӣ;+Z######DWk=C?|Xj9昇SekMs9NNVG@kD)4hn.Q@nJ)1]:;1@ T:ti:I$fM-+g]^LvIENDB`rdoc/generator/template/darkfish/images/wrench.png000064400000001142147635155430016343 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8˕oQ_[c+W.]хi5  g mJ[Fq#_)qո;,@{;upLTʙH$(Z XMɤni"\nt:}yD 0 \ ږIU4(r HMk̈_4_ziy'"[ n1rM_A`b=$Ik_p-qS~=li~3Bv"qZAԧ̸r[G]<&e!'ڸ67 yq$OX!=_~1Gs~EZQx&qWK3!ޤunkzGrjQnIENDB`rdoc/generator/template/darkfish/images/ruby.png000064400000001120147635155430016032 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8͓KQ &*z( z24r!\e77V"x!bT7R*c <||:[WAD>9{Li'v%IID=z/;"\k޸)ku9x]2$W0= $QH>}F|`n6ϜϤkN7 >9LL(,.}>ּ^ OMM|%꿏:/T]F$ 6VW))t5FKòQq"rf y_Oa| pHJ*MTX8[^Dr-||[v(33!.44NJebʡrטu͚d+@ S[Ko~TKrjkoraPDPy5@Y?i܅Sg@'˼Zj_M5̻w. ;'5ڿ_IENDB`rdoc/generator/template/darkfish/images/macFFBgHack.png000064400000000317147635155430017074 0ustar00PNG  IHDRcsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS3FtEXtCreation Time7/16/07Z (IDATHA0!U[ GϱJJJJJJJJJYIENDB`rdoc/generator/template/darkfish/images/date.png000064400000001162147635155430015774 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8˕RmkA~ԋK$5X% ǂ!#?P@PZ(*EA#ܹۙw:0;3ϼ@J f?WoL` OZ+M9cktyx D7гm\PSt]Io@#/د)[f^ѻ#dHkbG"uݿq\.Xc8YhH|r}/!FsRB(]jT5V?ZxYl6sd2QgwpdC2p8A厊*X,¢<}" W  8s"jR--tiM1eK lT*=L/F#C7~ -:MW1IENDB`rdoc/generator/template/darkfish/images/loadingAnimation.gif000064400000013376147635155430020327 0ustar00GIF89a ! NETSCAPE2.0! ,  @Rihlp,tm#6N+rrD4h@FCjz]Lj]﹬R3-H$wPy |KI\K Q\]PI ~$ ~ J %:`@ XP@AO 2|(D**HE}lF=$Ƌ@\9L J()? ``C=4RO@>}5TDU^=UQH~Xe֫:|AoG4Q]V;ޙ  jUzҧ]$jQM ʆķ7721@ܒDH;܋%ЅqۛXMgNάgMWz!`dѥ]uja}a ݸ6;5լDzTh,5~z~@y[:3M7gG]q=@c5 4u흃5__9_AMtB\K ⵘ}" @lDiQu+baq&{#'LHjz"$& $B! ,  EI@*PR*;ò[Ll7DҎ%GI0)mIԲ`I}>ă}-RwFu}y|O(p*"rt{RA>( ^( "4 333..Чɞ v.*o 3u zz( D.z Ha рP*6=%8A%ϤH]JQ&2Lz녆Aɔ>50j( ]T.s *I@m:nTx^7}v(Hy!8/ 4^ֹGi`zA"?l8]'STҧX*3@XMS<@蜮-./Ay5|Uv۬ϰVr4<A:\4bmdvi{˿ӛW'7naq{"8V_u_^2_[koTpbp :M skx_"Vؓ! ,  %R4 yԬԢ\K٩l'#QZ0ՠVTyïe]U4f!Pc0zkW+_ ^ў`v"Ŋa@x:@O,ȬtK5zsRtH5y3ʥ>yz=3[/Z|&x @7nGdn B^|{ZCN3Z&$p{f;^C}Co %! ,  %$5,%:k.]#> B"ZRp]2Shk9E-e<ͩkGj6-twsz|mOQtix41 ) U"  BQ B)# B+u  )ێ #" pg߿=QǍPa Q*֑Xb<88l$Q,? y2=0յT#rΗ5 9`jLmgTJ2MWy6jukիKy0iP0JCg&(`oq]혗']u}C*  ^\sxaGtKpeÈa@jvlgVDz$ͣQ>mb16}4 @l`ѪzvsGt 2y֐/V+SNJ=^"+Y  09ڛ>0}Lj`abqO '8^Xd|5 [ahWY7֑W6!i!qHX&(@3&B! ,  Q$@RS" k; S]3X'+ζS tUik `m0c]wldt$v}k~zq,lryux?)B ; 00;+ ­G 0-g+ .z%$z +l(jx9hNt<; 8O7yxH#|bH$ѼLipȅѐ 2"-A(P$tj@{s(W$( =!u5(jmn wmĸoA@w/d1+:'l1f#|,z20Hg@1}թٯ[3S+|7Uǃ.{ P卵0ʶc=+PL03:~p'v{On<~)@uP6 k (àK'vK V`I9(ZLG!! ,  PeRN*',Ԣv*o<bKs M3k>oR sAE1fm):kvvM{wl rtqPm|uF~?W a3& A66 - 3- .,6o 3/h-o 'dzz&(CGo߉Oa9ќD= kOOEuj(ǑLʏTIR&K.H= ttI£B0E:qjԪPhY‰ ʾBFdÎT0@ܝK!Aݽ_aw9hP(!Ѣ,fʓmZ,rƝ[|.1鑣wZh%.:^mRi綽7V޿}c\u;o>oüu+],Ebd]/\.*h3;߯~ |HoXg6] !! ,  E9$#%5(,Ԓr(i0.݊`lXtD%ydJ6H^.pl[k=.˿(>Sx~gypv}lNtjx{e> ( ~~ -- ,-(Ĺ ' e -/p(u '" u GN šL1:I<9uG '9cɕ-Q$L'lD7UTTׄ tѦBU@%JJŪ)W?LSY bZvmމБ]xF0I{VXg|-BfE#|.@4OP4u8S g ֥_n;Ө՞(բQ)wǮ<.(ʳ2?eG|LՅ"x/-/y+,p=E1 dQٷ~2Kꔛ$r `m*YsC zFn ak}nnI#Q! ,  %R4Ԝ"CA,(~ں8׼دDA֐2hs݌+p]ˤObKw8^>uz`H~htkv"xm|1Z, -#51"1''[#, ,}, ' p#h1 w a"w #p"b1V-akcB)P@;]XqČ#N-A"߲SyrL4eMʚph\@eq/o D2(𯘳q s:gu@Fu+QAUӯZ#xbR4vG1 Mɻ;8FP`B۩3he11O~ ˟>z(C3A=\Z-ڇAa-qiSRYmG(1;Ž=dtqB[! ,  %dihlp,40T:Ԕn琘9␄\< P)JZ+^f(-N Ǥ4ant#o~$z|u#Svx@"'% #m# S%  $%§ #ְͽ$& A"%  $#H݃'/9BH EdOC)Lq#Fo gBbDIʤC'CRg̙G 4^M=F\dd3 X堙Kl٣̊@@T?}IVUT+ol|gr TeluӭޒvG]l<ݑsg_D )4EQ_i)Pi#!h Da %.@qMOQ `pnyHWC"$s* ]hp$V 8};x3o}~Wtܠ$SjbjLEMa8y޿ww>JҪ*m*u=g6=W|vjz :@B(%UZ4\1mfj"jAƚ6hT*J VZJZ $@10PHZ(} )Be  @)zcԊe 02FHd#W?9Wi!Gc{sގl6IENDB`rdoc/generator/template/darkfish/images/find.png000064400000001223147635155430015775 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<%IDAT8c?%4ydÞ'/XfƦ"ʀGviQTo@5 )%k;o47Y%u ZbVTyE,Xݣo6ةm=x)k?"eKZ帹yLe? '?e}KjmѹÓ .dfay 6\Vo]Z9մ6\K/bĬ` *YBc~Z: ola_[S1qIbR/*.?##;L@ : ]_@$e;@1/x%|W4 |F=c 9WA12 5zaN?(8SSQEQBZ(`‚?֎nx% P`_IU P,aj(X@K*п9}ce&R12hZDÔ?R;c}s}Wb{{Jlff`[%nJs.Û/ZA8>>FP@>5}q$ {_Kx<B!y+qIEauuNS1stpppLMM;99G T/=/ LNNaOd2H$8;;9pzzZtxggp^W" bbbBU$A:-"WU9D6nnnJJUUqssd2X,&U]HtF'$fS4 x\>CvXZZdjr*^GQR)גct]l6GMr8d0e\SS$immMWp544zzzIpuu^u90_9>^WTT| P]]: $AWÃw{5nZZZ&c]5}EP^^`0,˃cccW/"֘kX YjIENDB`rdoc/generator/template/darkfish/images/page_white_width.png000064400000000465147635155430020377 0ustar00PNG  IHDR7gAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT(υA0E֕n\xqob♼ Rw(gIu2U5S6VXʲJ6YhlOe<Ƥj56S&5n2 ,be %,r[;zֳ X`<ƐdzB7|!A/n2=VY ro vZdIENDB`rdoc/generator/template/darkfish/images/tag_blue.png000064400000003530147635155430016642 0ustar00PNG  IHDRagAMA7iCCPICC ProfilexTkPe:g >hndStCkWZ6!Hm\$~ًo:w> كo{ a"L"4M'S9'^qZ/USO^C+hMJ&G@Ӳylto߫c՚  5"Yi\t։15LsX g8ocግ#f45@ B:K@8i ΁'&.)@ry[:Vͦ#wQ?HBd(B acĪL"JitTy8;(Gx_^[%׎ŷQ麲uan7m QH^eOQu6Su 2%vX ^*l O—ޭˀq,>S%LdB1CZ$M9P 'w\/].r#E|!3>_oa۾d1Zӑz'=~V+cjJtO%mN |-bWO+ o ^ IH.;S]i_s9*p.7U^s.3u |^,<;c=ma>Vt.[՟Ϫ x# ¡_2 pHYs  diTXtXML:com.adobe.xmp Adobe ImageReady z`IDAT8}RMka~vW#j-įV&ZjR B"Q!zR!JA"T ~zi*U̶G_ݝ}gyEQp:::+z2t~&΍o*Lo$d2ee ' V @43H6DX0O@(RmFٍodFɾ͇xUp:<"NTd}\3,@AZrr7! tZWwF_Z>lhRlޢlk1<\ؼ * q:ZUB:{ےܡP@Melۀ^z>:D"1iXZ {e<)iJl En)ev`POydb=;;CX.c k1k&8jר_ d{~?jcfiRԡsbOA9&ydV;8$p.r=XLv}@!OaX,*C;zJnYTaB!^L{n7kIENDB`rdoc/generator/template/darkfish/images/tag_green.png000064400000001145147635155430017013 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8˅IaOUÿ {bFcN4FMtn-=6c li4BH!(dX՗.U>BZERA\FTBXDP}!r^C2^@I`&tl $ɝ,S3MD.' 90NCӴY6)F?2m$ b @WH<Nt͐xj D"5v1of^gVfI.lfhě9<VOC|8i4>C8%JlGk8z#SmȉrXZ\@{x<.`^or ŌBx<^'j}U1}QWhT ]"kL|snێ# ~ߢK\}bx'BQ'{i^oPȲz].c)weSL|iW(SIENDB`rdoc/generator/template/darkfish/images/bullet_toggle_minus.png000064400000000317147635155430021123 0ustar00PNG  IHDR7gAMA7tEXtSoftwareAdobe ImageReadyqe<aIDAT(cπ2Q+/ދEp, %ւ)XC۱)XdB=6PMu][z+_70!IȓzS5IENDB`rdoc/generator/template/darkfish/images/transparent.png000064400000000141147635155430017414 0ustar00PNG  IHDR%=m"PLTEtRNS@f IDATc` 0zIENDB`rdoc/generator/template/darkfish/images/add.png000064400000001335147635155430015611 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<oIDAT8˥Ka[/Y()%X(olNۖskn.-h;8fEP"jïMGˈ}yພ羹$I.tulu AX:𼂒ZHh1DnZJOJB{Z?`2`S=N$ő=;a &jw qJG#<"N2h8޵`6xցn_+ ~Zto}`x%XЛ͈ hXѿƻ/}BJ_G&|Qr-6Aރ EL⬡\U3:WUh[C6+ 6.f *K͸ܝFq ou4܄?d|XҥMvD` *_[ #A20liR|xq`4w=\uQ m+G|%$5Թ5RO*YGMUO Gqj4ְ(X& s1c˭(LVf RdjQ '-1ATA>U j4,pV"4L$e@.ArBY a~myY])Q8tNLܞt2"I o=CSd)__AF(IENDB`rdoc/generator/template/darkfish/images/brick.png000064400000000704147635155430016152 0ustar00PNG  IHDR7gAMA7tEXtSoftwareAdobe ImageReadyqe<VIDAT?HTݝ^ٟ ju ɥpOhi/8ԩ!p*0Ў;}E,tnM2|13 "byK$i^NFDЙ;4eZ|Uj|jf^$ig)kYbIuKWPcJ'U>4MKB݆eSJtO9iԄ ʆn#2u` *_ R4+*BuϘMYU׷oAaLG۽kE|"2w9m[yGwSB3{er~㫹<{ @% @IENDB`rdoc/generator/template/darkfish/images/bug.png000064400000001406147635155430015635 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8˝OSQ\^[تtz% l$***2: iRp c0ąKw&&`44(eKɽwwrOX\HiscUQz@;քIdTaˀ)jC'يKT8=ʯ9ނ^zΘ1OFZ[W-Gz?&%*MGnN!aO>Nc[ɨX·0Nqg*1Sub|{g|fz)̾&\ 5\ 0 3i D;`|0>A?Tx4^`oqs`>ʦ`fCv@mX[r\At.)G[ Ì`N1)BWs+:NdsVa*DX.pB&B]H@T3@Pڏڠ wVP63yp-4 Ǽ $H'9{m@U$ZjCX:TgL::?[#{1P=.2F\iA-D 77qXIפb4kaAj% ͼj&Q˫H&s. `jKLE3*ΫX w6_l=@hߊv ,qqIENDB`rdoc/generator/template/darkfish/images/zoom.png000064400000001264147635155430016046 0ustar00PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<FIDAT8ˍKHA̪-KC= CmfuP)DB"K$A etJZyum0}f~3#sL|!!|g-V9Q鎺c`TC8*5bF'R!DЋ kb^sP!Locgע≣.=^u֘[ 65޶FG ! P %wN5\q=(t@ȀѶ(t2)է"L?B2uXcYV$&a]ct< *Q1}E )hYҁ갎6` DXr<:=UR̞O98*}V&b==hցqف+;˜JT<A!C:̼}nAH~0bM36 +/痗sIĢ̾Ek J {v!=_MyKb]öa{6W0378ɀQe6LIt殷cq!z |v j/Xi@ %1|hl !|! Y#uUNw]˼ H3u t]E>k%IfoRD:0`~ | (r on3oG0!$V *[W0_-+ dW&2ZfMFVJpiF&B > Rg- ~ CmڴER ឫ p5ްy+21Kawh` #aZ񽞆TZoLѓ`"(?'ˎJvKކ|:G9[aw82 Jw f'ymzsӘTsw__ιIrIENDB`rdoc/generator/template/darkfish/_sidebar_includes.rhtml000064400000000743147635155430017616 0ustar00<% unless klass.includes.empty? then %> <% end %> rdoc/generator/template/darkfish/_sidebar_classes.rhtml000064400000000460147635155430017441 0ustar00 rdoc/generator/template/json_index/js/searcher.js000064400000014713147635155430016225 0ustar00Searcher = function(data) { this.data = data; this.handlers = []; } Searcher.prototype = new function() { // search is performed in chunks of 1000 for non-blocking user input var CHUNK_SIZE = 1000; // do not try to find more than 100 results var MAX_RESULTS = 100; var huid = 1; var suid = 1; var runs = 0; this.find = function(query) { var queries = splitQuery(query); var regexps = buildRegexps(queries); var highlighters = buildHilighters(queries); var state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++}; var _this = this; this.currentSuid = state.n; if (!query) return; var run = function() { // stop current search thread if new search started if (state.n != _this.currentSuid) return; var results = performSearch(_this.data, regexps, queries, highlighters, state); var hasMore = (state.limit > 0 && state.pass < 4); triggerResults.call(_this, results, !hasMore); if (hasMore) { setTimeout(run, 2); } runs++; }; runs = 0; // start search thread run(); } /* ----- Events ------ */ this.ready = function(fn) { fn.huid = huid; this.handlers.push(fn); } /* ----- Utilities ------ */ function splitQuery(query) { return jQuery.grep(query.split(/(\s+|::?|\(\)?)/), function(string) { return string.match(/\S/) }); } function buildRegexps(queries) { return jQuery.map(queries, function(query) { return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i') }); } function buildHilighters(queries) { return jQuery.map(queries, function(query) { return jQuery.map(query.split(''), function(l, i) { return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2); }).join(''); }); } // function longMatchRegexp(index, longIndex, regexps) { // for (var i = regexps.length - 1; i >= 0; i--){ // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; // }; // return true; // } /* ----- Mathchers ------ */ /* * This record matches if the index starts with queries[0] and the record * matches all of the regexps */ function matchPassBeginning(index, longIndex, queries, regexps) { if (index.indexOf(queries[0]) != 0) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; }; return true; } /* * This record matches if the longIndex starts with queries[0] and the * longIndex matches all of the regexps */ function matchPassLongIndex(index, longIndex, queries, regexps) { if (longIndex.indexOf(queries[0]) != 0) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!longIndex.match(regexps[i])) return false; }; return true; } /* * This record matches if the index contains queries[0] and the record * matches all of the regexps */ function matchPassContains(index, longIndex, queries, regexps) { if (index.indexOf(queries[0]) == -1) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; }; return true; } /* * This record matches if regexps[0] matches the index and the record * matches all of the regexps */ function matchPassRegexp(index, longIndex, queries, regexps) { if (!index.match(regexps[0])) return false; for (var i=1, l = regexps.length; i < l; i++) { if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false; }; return true; } /* ----- Highlighters ------ */ function highlightRegexp(info, queries, regexps, highlighters) { var result = createResult(info); for (var i=0, l = regexps.length; i < l; i++) { result.title = result.title.replace(regexps[i], highlighters[i]); result.namespace = result.namespace.replace(regexps[i], highlighters[i]); }; return result; } function hltSubstring(string, pos, length) { return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length); } function highlightQuery(info, queries, regexps, highlighters) { var result = createResult(info); var pos = 0; var lcTitle = result.title.toLowerCase(); pos = lcTitle.indexOf(queries[0]); if (pos != -1) { result.title = hltSubstring(result.title, pos, queries[0].length); } result.namespace = result.namespace.replace(regexps[0], highlighters[0]); for (var i=1, l = regexps.length; i < l; i++) { result.title = result.title.replace(regexps[i], highlighters[i]); result.namespace = result.namespace.replace(regexps[i], highlighters[i]); }; return result; } function createResult(info) { var result = {}; result.title = info[0]; result.namespace = info[1]; result.path = info[2]; result.params = info[3]; result.snippet = info[4]; return result; } /* ----- Searching ------ */ function performSearch(data, regexps, queries, highlighters, state) { var searchIndex = data.searchIndex; var longSearchIndex = data.longSearchIndex; var info = data.info; var result = []; var i = state.from; var l = searchIndex.length; var togo = CHUNK_SIZE; var matchFunc, hltFunc; while (state.pass < 4 && state.limit > 0 && togo > 0) { if (state.pass == 0) { matchFunc = matchPassBeginning; hltFunc = highlightQuery; } else if (state.pass == 1) { matchFunc = matchPassLongIndex; hltFunc = highlightQuery; } else if (state.pass == 2) { matchFunc = matchPassContains; hltFunc = highlightQuery; } else if (state.pass == 3) { matchFunc = matchPassRegexp; hltFunc = highlightRegexp; } for (; togo > 0 && i < l && state.limit > 0; i++, togo--) { if (info[i].n == state.n) continue; if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) { info[i].n = state.n; result.push(hltFunc(info[i], queries, regexps, highlighters)); state.limit--; } }; if (searchIndex.length <= i) { state.pass++; i = state.from = 0; } else { state.from = i; } } return result; } function triggerResults(results, isLast) { jQuery.each(this.handlers, function(i, fn) { fn.call(this, results, isLast) }) } } rdoc/generator/template/json_index/js/navigation.js000064400000007117147635155430016570 0ustar00/* * Navigation allows movement using the arrow keys through the search results. * * When using this library you will need to set scrollIntoView to the * appropriate function for your layout. Use scrollInWindow if the container * is not scrollable and scrollInElement if the container is a separate * scrolling region. */ Navigation = new function() { this.initNavigation = function() { var _this = this; $(document).keydown(function(e) { _this.onkeydown(e); }).keyup(function(e) { _this.onkeyup(e); }); this.navigationActive = true; } this.setNavigationActive = function(state) { this.navigationActive = state; this.clearMoveTimeout(); } this.onkeyup = function(e) { if (!this.navigationActive) return; switch(e.keyCode) { case 37: //Event.KEY_LEFT: case 38: //Event.KEY_UP: case 39: //Event.KEY_RIGHT: case 40: //Event.KEY_DOWN: this.clearMoveTimeout(); break; } } this.onkeydown = function(e) { if (!this.navigationActive) return; switch(e.keyCode) { case 37: //Event.KEY_LEFT: if (this.moveLeft()) e.preventDefault(); break; case 38: //Event.KEY_UP: if (e.keyCode == 38 || e.ctrlKey) { if (this.moveUp()) e.preventDefault(); this.startMoveTimeout(false); } break; case 39: //Event.KEY_RIGHT: if (this.moveRight()) e.preventDefault(); break; case 40: //Event.KEY_DOWN: if (e.keyCode == 40 || e.ctrlKey) { if (this.moveDown()) e.preventDefault(); this.startMoveTimeout(true); } break; case 13: //Event.KEY_RETURN: if (this.$current) e.preventDefault(); this.select(this.$current); break; } if (e.ctrlKey && e.shiftKey) this.select(this.$current); } this.clearMoveTimeout = function() { clearTimeout(this.moveTimeout); this.moveTimeout = null; } this.startMoveTimeout = function(isDown) { if (!$.browser.mozilla && !$.browser.opera) return; if (this.moveTimeout) this.clearMoveTimeout(); var _this = this; var go = function() { if (!_this.moveTimeout) return; _this[isDown ? 'moveDown' : 'moveUp'](); _this.moveTimout = setTimeout(go, 100); } this.moveTimeout = setTimeout(go, 200); } this.moveRight = function() { } this.moveLeft = function() { } this.move = function(isDown) { } this.moveUp = function() { return this.move(false); } this.moveDown = function() { return this.move(true); } /* * Scrolls to the given element in the scrollable element view. */ this.scrollInElement = function(element, view) { var offset, viewHeight, viewScroll, height; offset = element.offsetTop; height = element.offsetHeight; viewHeight = view.offsetHeight; viewScroll = view.scrollTop; if (offset - viewScroll + height > viewHeight) { view.scrollTop = offset - viewHeight + height; } if (offset < viewScroll) { view.scrollTop = offset; } } /* * Scrolls to the given element in the window. The second argument is * ignored */ this.scrollInWindow = function(element, ignored) { var offset, viewHeight, viewScroll, height; offset = element.offsetTop; height = element.offsetHeight; viewHeight = window.innerHeight; viewScroll = window.scrollY; if (offset - viewScroll + height > viewHeight) { window.scrollTo(window.scrollX, offset - viewHeight + height); } if (offset < viewScroll) { window.scrollTo(window.scrollX, offset); } } } rdoc/generator/markup.rb000064400000006670147635155430011333 0ustar00## # Handle common RDoc::Markup tasks for various CodeObjects # # This module is loaded by generators. It allows RDoc's CodeObject tree to # avoid loading generator code to improve startup time for +ri+. module RDoc::Generator::Markup ## # Generates a relative URL from this object's path to +target_path+ def aref_to(target_path) RDoc::Markup::ToHtml.gen_relative_url path, target_path end ## # Generates a relative URL from +from_path+ to this object's path def as_href(from_path) RDoc::Markup::ToHtml.gen_relative_url from_path, path end ## # Handy wrapper for marking up this object's comment def description markup @comment end ## # Creates an RDoc::Markup::ToHtmlCrossref formatter def formatter return @formatter if defined? @formatter options = @store.rdoc.options this = RDoc::Context === self ? self : @parent @formatter = RDoc::Markup::ToHtmlCrossref.new options, this.path, this @formatter.code_object = self @formatter end ## # Build a webcvs URL starting for the given +url+ with +full_path+ appended # as the destination path. If +url+ contains '%s' +full_path+ will be # will replace the %s using sprintf on the +url+. def cvs_url(url, full_path) if /%s/ =~ url then sprintf url, full_path else url + full_path end end end class RDoc::CodeObject include RDoc::Generator::Markup end class RDoc::MethodAttr @add_line_numbers = false class << self ## # Allows controlling whether #markup_code adds line numbers to # the source code. attr_accessor :add_line_numbers end ## # Prepend +src+ with line numbers. Relies on the first line of a source # code listing having: # # # File xxxxx, line dddd # # If it has this comment then line numbers are added to +src+ and the , # line dddd portion of the comment is removed. def add_line_numbers(src) return unless src.sub!(/\A(.*)(, line (\d+))/, '\1') first = $3.to_i - 1 last = first + src.count("\n") size = last.to_s.length line = first src.gsub!(/^/) do res = if line == first then " " * (size + 1) else "%2$*1$d " % [size, line] end line += 1 res end end ## # Turns the method's token stream into HTML. # # Prepends line numbers if +add_line_numbers+ is true. def markup_code return '' unless @token_stream src = RDoc::TokenStream.to_html @token_stream # dedent the source indent = src.length lines = src.lines.to_a lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment lines.each do |line| if line =~ /^ *(?=\S)/ n = $&.length indent = n if n < indent break if n == 0 end end src.gsub!(/^#{' ' * indent}/, '') if indent > 0 add_line_numbers(src) if RDoc::MethodAttr.add_line_numbers src end end class RDoc::ClassModule ## # Handy wrapper for marking up this class or module's comment def description markup @comment_location end end class RDoc::Context::Section include RDoc::Generator::Markup end class RDoc::TopLevel ## # Returns a URL for this source file on some web repository. Use the -W # command line option to set. def cvs_url url = @store.rdoc.options.webcvs if /%s/ =~ url then url % @relative_name else url + @relative_name end end end rdoc/ghost_method.rb000064400000000162147635155430010520 0ustar00## # GhostMethod represents a method referenced only by a comment class RDoc::GhostMethod < RDoc::AnyMethod end rdoc/erbio.rb000064400000001432147635155430007135 0ustar00require 'erb' ## # A subclass of ERB that writes directly to an IO. Credit to Aaron Patterson # and Masatoshi SEKI. # # To use: # # erbio = RDoc::ERBIO.new '<%= "hello world" %>', nil, nil # # open 'hello.txt', 'w' do |io| # erbio.result binding # end # # Note that binding must enclose the io you wish to output on. class RDoc::ERBIO < ERB ## # Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize def initialize str, safe_level = nil, trim_mode = nil, eoutvar = 'io' super end ## # Instructs +compiler+ how to write to +io_variable+ def set_eoutvar compiler, io_variable compiler.put_cmd = "#{io_variable}.write" compiler.insert_cmd = "#{io_variable}.write" compiler.pre_cmd = [] compiler.post_cmd = [] end end rdoc/servlet.rb000064400000025523147635155430007530 0ustar00require 'rdoc' require 'time' require 'webrick' ## # This is a WEBrick servlet that allows you to browse ri documentation. # # You can show documentation through either `ri --server` or, with RubyGems # 2.0 or newer, `gem server`. For ri, the server runs on port 8214 by # default. For RubyGems the server runs on port 8808 by default. # # You can use this servlet in your own project by mounting it on a WEBrick # server: # # require 'webrick' # # server = WEBrick::HTTPServer.new Port: 8000 # # server.mount '/', RDoc::Servlet # # If you want to mount the servlet some other place than the root, provide the # base path when mounting: # # server.mount '/rdoc', RDoc::Servlet, '/rdoc' class RDoc::Servlet < WEBrick::HTTPServlet::AbstractServlet @server_stores = Hash.new { |hash, server| hash[server] = {} } @cache = Hash.new { |hash, store| hash[store] = {} } ## # Maps an asset type to its path on the filesystem attr_reader :asset_dirs ## # An RDoc::Options instance used for rendering options attr_reader :options ## # Creates an instance of this servlet that shares cached data between # requests. def self.get_instance server, *options # :nodoc: stores = @server_stores[server] new server, stores, @cache, *options end ## # Creates a new WEBrick servlet. # # Use +mount_path+ when mounting the servlet somewhere other than /. # # +server+ is provided automatically by WEBrick when mounting. +stores+ and # +cache+ are provided automatically by the servlet. def initialize server, stores, cache, mount_path = nil super server @cache = cache @mount_path = mount_path @stores = stores @options = RDoc::Options.new @options.op_dir = '.' darkfish_dir = nil # HACK dup $LOAD_PATH.each do |path| darkfish_dir = File.join path, 'rdoc/generator/template/darkfish/' next unless File.directory? darkfish_dir @options.template_dir = darkfish_dir break end @asset_dirs = { :darkfish => darkfish_dir, :json_index => File.expand_path('../generator/template/json_index/', __FILE__), } end ## # Serves the asset at the path in +req+ for +generator_name+ via +res+. def asset generator_name, req, res asset_dir = @asset_dirs[generator_name] asset_path = File.join asset_dir, req.path if_modified_since req, res, asset_path res.body = File.read asset_path res.content_type = case req.path when /css$/ then 'text/css' when /js$/ then 'application/javascript' else 'application/octet-stream' end end ## # GET request entry point. Fills in +res+ for the path, etc. in +req+. def do_GET req, res req.path.sub!(/^#{Regexp.escape @mount_path}/o, '') if @mount_path case req.path when '/' then root req, res when '/rdoc.css', '/js/darkfish.js', '/js/jquery.js', '/js/search.js', %r%^/images/% then asset :darkfish, req, res when '/js/navigation.js', '/js/searcher.js' then asset :json_index, req, res when '/js/search_index.js' then root_search req, res else show_documentation req, res end rescue WEBrick::HTTPStatus::Status raise rescue => e error e, req, res end ## # Fills in +res+ with the class, module or page for +req+ from +store+. # # +path+ is relative to the mount_path and is used to determine the class, # module or page name (/RDoc/Servlet.html becomes RDoc::Servlet). # +generator+ is used to create the page. def documentation_page store, generator, path, req, res name = path.sub(/.html$/, '').gsub '/', '::' if klass = store.find_class_or_module(name) then res.body = generator.generate_class klass elsif page = store.find_text_page(name.sub(/_([^_]*)$/, '.\1')) then res.body = generator.generate_page page else not_found generator, req, res end end ## # Creates the JSON search index on +res+ for the given +store+. +generator+ # must respond to \#json_index to build. +req+ is ignored. def documentation_search store, generator, req, res json_index = @cache[store].fetch :json_index do @cache[store][:json_index] = JSON.dump generator.json_index.build_index end res.content_type = 'application/javascript' res.body = "var search_data = #{json_index}" end ## # Returns the RDoc::Store and path relative to +mount_path+ for # documentation at +path+. def documentation_source path _, source_name, path = path.split '/', 3 store = @stores[source_name] return store, path if store store = store_for source_name store.load_all @stores[source_name] = store return store, path end ## # Generates an error page for the +exception+ while handling +req+ on +res+. def error exception, req, res backtrace = exception.backtrace.join "\n" res.content_type = 'text/html' res.status = 500 res.body = <<-BODY Error - #{ERB::Util.html_escape exception.class}

    Error

    While processing #{ERB::Util.html_escape req.request_uri} the RDoc (#{ERB::Util.html_escape RDoc::VERSION}) server has encountered a #{ERB::Util.html_escape exception.class} exception:

    #{ERB::Util.html_escape exception.message}

    Please report this to the RDoc issues tracker. Please include the RDoc version, the URI above and exception class, message and backtrace. If you're viewing a gem's documentation, include the gem name and version. If you're viewing Ruby's documentation, include the version of ruby.

    Backtrace:

    #{ERB::Util.html_escape backtrace}
    BODY end ## # Instantiates a Darkfish generator for +store+ def generator_for store generator = RDoc::Generator::Darkfish.new store, @options generator.file_output = false generator.asset_rel_path = '..' rdoc = RDoc::RDoc.new rdoc.store = store rdoc.generator = generator rdoc.options = @options @options.main_page = store.main @options.title = store.title generator end ## # Handles the If-Modified-Since HTTP header on +req+ for +path+. If the # file has not been modified a Not Modified response is returned. If the # file has been modified a Last-Modified header is added to +res+. def if_modified_since req, res, path = nil last_modified = File.stat(path).mtime if path res['last-modified'] = last_modified.httpdate return unless ims = req['if-modified-since'] ims = Time.parse ims unless ims < last_modified then res.body = '' raise WEBrick::HTTPStatus::NotModified end end ## # Returns an Array of installed documentation. # # Each entry contains the documentation name (gem name, 'Ruby # Documentation', etc.), the path relative to the mount point, whether the # documentation exists, the type of documentation (See RDoc::RI::Paths#each) # and the filesystem to the RDoc::Store for the documentation. def installed_docs ri_paths.map do |path, type| store = RDoc::Store.new path, type exists = File.exist? store.cache_path case type when :gem then gem_path = path[%r%/([^/]*)/ri$%, 1] [gem_path, "#{gem_path}/", exists, type, path] when :system then ['Ruby Documentation', 'ruby/', exists, type, path] when :site then ['Site Documentation', 'site/', exists, type, path] when :home then ['Home Documentation', 'home/', exists, type, path] end end end ## # Returns a 404 page built by +generator+ for +req+ on +res+. def not_found generator, req, res res.body = generator.generate_servlet_not_found req.path res.status = 404 end ## # Enumerates the ri paths. See RDoc::RI::Paths#each def ri_paths &block RDoc::RI::Paths.each true, true, true, :all, &block end ## # Generates the root page on +res+. +req+ is ignored. def root req, res generator = RDoc::Generator::Darkfish.new nil, @options res.body = generator.generate_servlet_root installed_docs res.content_type = 'text/html' end ## # Generates a search index for the root page on +res+. +req+ is ignored. def root_search req, res search_index = [] info = [] installed_docs.map do |name, href, exists, type, path| next unless exists search_index << name case type when :gem gemspec = path.gsub(%r%/doc/([^/]*?)/ri$%, '/specifications/\1.gemspec') spec = Gem::Specification.load gemspec path = spec.full_name comment = spec.summary when :system then path = 'ruby' comment = 'Documentation for the Ruby standard library' when :site then path = 'site' comment = 'Documentation for non-gem libraries' when :home then path = 'home' comment = 'Documentation from your home directory' end info << [name, '', path, '', comment] end index = { :index => { :searchIndex => search_index, :longSearchIndex => search_index, :info => info, } } res.body = "var search_data = #{JSON.dump index};" res.content_type = 'application/javascript' end ## # Displays documentation for +req+ on +res+, whether that be HTML or some # asset. def show_documentation req, res store, path = documentation_source req.path if_modified_since req, res, store.cache_path generator = generator_for store case path when nil, '', 'index.html' then res.body = generator.generate_index when 'table_of_contents.html' then res.body = generator.generate_table_of_contents when 'js/search_index.js' then documentation_search store, generator, req, res else documentation_page store, generator, path, req, res end ensure res.content_type ||= 'text/html' end ## # Returns an RDoc::Store for the given +source_name+ ('ruby' or a gem name). def store_for source_name case source_name when 'home' then RDoc::Store.new RDoc::RI::Paths.home_dir, :home when 'ruby' then RDoc::Store.new RDoc::RI::Paths.system_dir, :system when 'site' then RDoc::Store.new RDoc::RI::Paths.site_dir, :site else ri_dir, type = ri_paths.find do |dir, dir_type| next unless dir_type == :gem source_name == dir[%r%/([^/]*)/ri$%, 1] end raise RDoc::Error, "could not find ri documentation for #{source_name}" unless ri_dir RDoc::Store.new ri_dir, type end end end rdoc/method_attr.rb000064400000021105147635155430010346 0ustar00## # Abstract class representing either a method or an attribute. class RDoc::MethodAttr < RDoc::CodeObject include Comparable ## # Name of this method/attribute. attr_accessor :name ## # public, protected, private attr_accessor :visibility ## # Is this a singleton method/attribute? attr_accessor :singleton ## # Source file token stream attr_reader :text ## # Array of other names for this method/attribute attr_reader :aliases ## # The method/attribute we're aliasing attr_accessor :is_alias_for #-- # The attributes below are for AnyMethod only. # They are left here for the time being to # allow ri to operate. # TODO modify ri to avoid calling these on attributes. #++ ## # Parameters yielded by the called block attr_reader :block_params ## # Parameters for this method attr_accessor :params ## # Different ways to call this method attr_accessor :call_seq ## # The call_seq or the param_seq with method name, if there is no call_seq. attr_reader :arglists ## # Pretty parameter list for this method attr_reader :param_seq ## # Creates a new MethodAttr from token stream +text+ and method or attribute # name +name+. # # Usually this is called by super from a subclass. def initialize text, name super() @text = text @name = name @aliases = [] @is_alias_for = nil @parent_name = nil @singleton = nil @visibility = :public @see = false @arglists = nil @block_params = nil @call_seq = nil @param_seq = nil @params = nil end ## # Order by #singleton then #name def <=>(other) [ @singleton ? 0 : 1, name] <=> [other.singleton ? 0 : 1, other.name] end def == other # :nodoc: super or self.class == other.class and full_name == other.full_name end ## # A method/attribute is documented if any of the following is true: # - it was marked with :nodoc:; # - it has a comment; # - it is an alias for a documented method; # - it has a +#see+ method that is documented. def documented? super or (is_alias_for and is_alias_for.documented?) or (see and see.documented?) end ## # A method/attribute to look at, # in particular if this method/attribute has no documentation. # # It can be a method/attribute of the superclass or of an included module, # including the Kernel module, which is always appended to the included # modules. # # Returns +nil+ if there is no such method/attribute. # The +#is_alias_for+ method/attribute, if any, is not included. # # Templates may generate a "see also ..." if this method/attribute # has documentation, and "see ..." if it does not. def see @see = find_see if @see == false @see end ## # Sets the store for this class or module and its contained code objects. def store= store super @file = @store.add_file @file.full_name if @file end def find_see # :nodoc: return nil if singleton || is_alias_for # look for the method other = find_method_or_attribute name return other if other # if it is a setter, look for a getter return nil unless name =~ /[a-z_]=$/i # avoid == or === return find_method_or_attribute name[0..-2] end def find_method_or_attribute name # :nodoc: return nil unless parent.respond_to? :ancestors searched = parent.ancestors kernel = @store.modules_hash['Kernel'] searched << kernel if kernel && parent != kernel && !searched.include?(kernel) searched.each do |ancestor| next if parent == ancestor next if String === ancestor other = ancestor.find_method_named('#' << name) || ancestor.find_attribute_named(name) return other if other end nil end ## # Abstract method. Contexts in their building phase call this # to register a new alias for this known method/attribute. # # - creates a new AnyMethod/Attribute named an_alias.new_name; # - adds +self+ as an alias for the new method or attribute # - adds the method or attribute to #aliases # - adds the method or attribute to +context+. def add_alias(an_alias, context) raise NotImplementedError end ## # HTML fragment reference for this method def aref type = singleton ? 'c' : 'i' # % characters are not allowed in html names => dash instead "#{aref_prefix}-#{type}-#{html_name}" end ## # Prefix for +aref+, defined by subclasses. def aref_prefix raise NotImplementedError end ## # Attempts to sanitize the content passed by the ruby parser: # remove outer parentheses, etc. def block_params=(value) # 'yield.to_s' or 'assert yield, msg' return @block_params = '' if value =~ /^[\.,]/ # remove trailing 'if/unless ...' return @block_params = '' if value =~ /^(if|unless)\s/ value = $1.strip if value =~ /^(.+)\s(if|unless)\s/ # outer parentheses value = $1 if value =~ /^\s*\((.*)\)\s*$/ value = value.strip # proc/lambda return @block_params = $1 if value =~ /^(proc|lambda)(\s*\{|\sdo)/ # surrounding +...+ or [...] value = $1.strip if value =~ /^\+(.*)\+$/ value = $1.strip if value =~ /^\[(.*)\]$/ return @block_params = '' if value.empty? # global variable return @block_params = 'str' if value =~ /^\$[&0-9]$/ # wipe out array/hash indices value.gsub!(/(\w)\[[^\[]+\]/, '\1') # remove @ from class/instance variables value.gsub!(/@@?([a-z0-9_]+)/, '\1') # method calls => method name value.gsub!(/([A-Z:a-z0-9_]+)\.([a-z0-9_]+)(\s*\(\s*[a-z0-9_.,\s]*\s*\)\s*)?/) do case $2 when 'to_s' then $1 when 'const_get' then 'const' when 'new' then $1.split('::').last. # ClassName => class_name gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). gsub(/([a-z\d])([A-Z])/,'\1_\2'). downcase else $2 end end # class prefixes value.gsub!(/[A-Za-z0-9_:]+::/, '') # simple expressions value = $1 if value =~ /^([a-z0-9_]+)\s*[-*+\/]/ @block_params = value.strip end ## # HTML id-friendly method/attribute name def html_name require 'cgi' CGI.escape(@name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '') end ## # Full method/attribute name including namespace def full_name @full_name ||= "#{parent_name}#{pretty_name}" end def inspect # :nodoc: alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil visibility = self.visibility visibility = "forced #{visibility}" if force_documentation "#<%s:0x%x %s (%s)%s>" % [ self.class, object_id, full_name, visibility, alias_for, ] end ## # '::' for a class method/attribute, '#' for an instance method. def name_prefix @singleton ? '::' : '#' end ## # Name for output to HTML. For class methods the full name with a "." is # used like +SomeClass.method_name+. For instance methods the class name is # used if +context+ does not match the parent. # # This is to help prevent people from using :: to call class methods. def output_name context return "#{name_prefix}#{@name}" if context == parent "#{parent_name}#{@singleton ? '.' : '#'}#{@name}" end ## # Method/attribute name with class/instance indicator def pretty_name "#{name_prefix}#{@name}" end ## # Type of method/attribute (class or instance) def type singleton ? 'class' : 'instance' end ## # Path to this method for use with HTML generator output. def path "#{@parent.path}##{aref}" end ## # Name of our parent with special handling for un-marshaled methods def parent_name @parent_name || super end def pretty_print q # :nodoc: alias_for = @is_alias_for ? "alias for #{@is_alias_for.name}" : nil q.group 2, "[#{self.class.name} #{full_name} #{visibility}", "]" do if alias_for then q.breakable q.text alias_for end if text then q.breakable q.text "text:" q.breakable q.pp @text end unless comment.empty? then q.breakable q.text "comment:" q.breakable q.pp @comment end end end ## # Used by RDoc::Generator::JsonIndex to create a record for the search # engine. def search_record [ @name, full_name, @name, @parent.full_name, path, params, snippet(@comment), ] end def to_s # :nodoc: if @is_alias_for "#{self.class.name}: #{full_name} -> #{is_alias_for}" else "#{self.class.name}: #{full_name}" end end end rdoc/task.rb000064400000017244147635155430007007 0ustar00#-- # Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ require 'rubygems' begin gem 'rdoc' rescue Gem::LoadError end unless defined?(RDoc) begin gem 'rake' rescue Gem::LoadError end unless defined?(Rake) require 'rdoc' require 'rake' require 'rake/tasklib' ## # RDoc::Task creates the following rake tasks to generate and clean up RDoc # output: # # [rdoc] # Main task for this RDoc task. # # [clobber_rdoc] # Delete all the rdoc files. This target is automatically added to the main # clobber target. # # [rerdoc] # Rebuild the rdoc files from scratch, even if they are not out of date. # # Simple Example: # # require 'rdoc/task' # # RDoc::Task.new do |rdoc| # rdoc.main = "README.rdoc" # rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb") # end # # The +rdoc+ object passed to the block is an RDoc::Task object. See the # attributes list for the RDoc::Task class for available customization options. # # == Specifying different task names # # You may wish to give the task a different name, such as if you are # generating two sets of documentation. For instance, if you want to have a # development set of documentation including private methods: # # require 'rdoc/task' # # RDoc::Task.new :rdoc_dev do |rdoc| # rdoc.main = "README.doc" # rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb") # rdoc.options << "--all" # end # # The tasks would then be named :rdoc_dev, # :clobber_rdoc_dev, and :rerdoc_dev. # # If you wish to have completely different task names, then pass a Hash as # first argument. With the :rdoc, :clobber_rdoc and # :rerdoc options, you can customize the task names to your liking. # # For example: # # require 'rdoc/task' # # RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", # :rerdoc => "rdoc:force") # # This will create the tasks :rdoc, :rdoc:clean and # :rdoc:force. class RDoc::Task < Rake::TaskLib ## # Name of the main, top level task. (default is :rdoc) attr_accessor :name ## # Comment markup format. rdoc, rd and tomdoc are supported. (default is # 'rdoc') attr_accessor :markup ## # Name of directory to receive the html output files. (default is "html") attr_accessor :rdoc_dir ## # Title of RDoc documentation. (defaults to rdoc's default) attr_accessor :title ## # Name of file to be used as the main, top level file of the RDoc. (default # is none) attr_accessor :main ## # Name of template to be used by rdoc. (defaults to rdoc's default) attr_accessor :template ## # Name of format generator (--format) used by rdoc. (defaults to # rdoc's default) attr_accessor :generator ## # List of files to be included in the rdoc generation. (default is []) attr_accessor :rdoc_files ## # Additional list of options to be passed rdoc. (default is []) attr_accessor :options ## # Whether to run the rdoc process as an external shell (default is false) attr_accessor :external ## # Create an RDoc task with the given name. See the RDoc::Task class overview # for documentation. def initialize name = :rdoc # :yield: self defaults check_names name @name = name yield self if block_given? define end ## # Ensures that +names+ only includes names for the :rdoc, :clobber_rdoc and # :rerdoc. If other names are given an ArgumentError is raised. def check_names names return unless Hash === names invalid_options = names.keys.map { |k| k.to_sym } - [:rdoc, :clobber_rdoc, :rerdoc] unless invalid_options.empty? then raise ArgumentError, "invalid options: #{invalid_options.join ', '}" end end ## # Task description for the clobber rdoc task or its renamed equivalent def clobber_task_description "Remove RDoc HTML files" end ## # Sets default task values def defaults @name = :rdoc @rdoc_files = Rake::FileList.new @rdoc_dir = 'html' @main = nil @title = nil @template = nil @generator = nil @options = [] end ## # All source is inline now. This method is deprecated def inline_source # :nodoc: warn "RDoc::Task#inline_source is deprecated" true end ## # All source is inline now. This method is deprecated def inline_source=(value) # :nodoc: warn "RDoc::Task#inline_source is deprecated" end ## # Create the tasks defined by this task lib. def define desc rdoc_task_description task rdoc_task_name desc rerdoc_task_description task rerdoc_task_name => [clobber_task_name, rdoc_task_name] desc clobber_task_description task clobber_task_name do rm_r @rdoc_dir rescue nil end task :clobber => [clobber_task_name] directory @rdoc_dir rdoc_target_deps = [ @rdoc_files, Rake.application.rakefile ].flatten.compact task rdoc_task_name => [rdoc_target] file rdoc_target => rdoc_target_deps do @before_running_rdoc.call if @before_running_rdoc args = option_list + @rdoc_files $stderr.puts "rdoc #{args.join ' '}" if Rake.application.options.trace RDoc::RDoc.new.document args end self end ## # List of options that will be supplied to RDoc def option_list result = @options.dup result << "-o" << @rdoc_dir result << "--main" << main if main result << "--markup" << markup if markup result << "--title" << title if title result << "-T" << template if template result << '-f' << generator if generator result end ## # The block passed to this method will be called just before running the # RDoc generator. It is allowed to modify RDoc::Task attributes inside the # block. def before_running_rdoc(&block) @before_running_rdoc = block end ## # Task description for the rdoc task or its renamed equivalent def rdoc_task_description 'Build RDoc HTML files' end ## # Task description for the rerdoc task or its renamed description def rerdoc_task_description "Rebuild RDoc HTML files" end private def rdoc_target "#{rdoc_dir}/index.html" end def rdoc_task_name case name when Hash then (name[:rdoc] || "rdoc").to_s else name.to_s end end def clobber_task_name case name when Hash then (name[:clobber_rdoc] || "clobber_rdoc").to_s else "clobber_#{name}" end end def rerdoc_task_name case name when Hash then (name[:rerdoc] || "rerdoc").to_s else "re#{name}" end end end # :stopdoc: module Rake ## # For backwards compatibility RDocTask = RDoc::Task end # :startdoc: rdoc/parser/simple.rb000064400000002615147635155430010626 0ustar00## # Parse a non-source file. We basically take the whole thing as one big # comment. class RDoc::Parser::Simple < RDoc::Parser include RDoc::Parser::Text parse_files_matching(//) attr_reader :content # :nodoc: ## # Prepare to parse a plain file def initialize(top_level, file_name, content, options, stats) super preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include preprocess.handle @content, @top_level end ## # Extract the file contents and attach them to the TopLevel as a comment def scan comment = remove_coding_comment @content comment = remove_private_comment comment comment = RDoc::Comment.new comment, @top_level @top_level.comment = comment @top_level end ## # Removes the encoding magic comment from +text+ def remove_coding_comment text text.sub(/\A# .*coding[=:].*$/, '') end ## # Removes private comments. # # Unlike RDoc::Comment#remove_private this implementation only looks for two # dashes at the beginning of the line. Three or more dashes are considered # to be a rule and ignored. def remove_private_comment comment # Workaround for gsub encoding for Ruby 1.9.2 and earlier empty = '' empty.force_encoding comment.encoding if Object.const_defined? :Encoding comment = comment.gsub(%r%^--\n.*?^\+\+\n?%m, empty) comment.sub(%r%^--\n.*%m, empty) end end rdoc/parser/text.rb000064400000000425147635155430010316 0ustar00## # Indicates this parser is text and doesn't contain code constructs. # # Include this module in a RDoc::Parser subclass to make it show up as a file, # not as part of a class or module. #-- # This is not named File to avoid overriding ::File module RDoc::Parser::Text end rdoc/parser/ruby_tools.rb000064400000005670147635155430011542 0ustar00## # Collection of methods for writing parsers against RDoc::RubyLex and # RDoc::RubyToken module RDoc::Parser::RubyTools include RDoc::RubyToken ## # Adds a token listener +obj+, but you should probably use token_listener def add_token_listener(obj) @token_listeners ||= [] @token_listeners << obj end ## # Fetches the next token from the scanner def get_tk tk = nil if @tokens.empty? then tk = @scanner.token @read.push @scanner.get_readed puts "get_tk1 => #{tk.inspect}" if $TOKEN_DEBUG else @read.push @unget_read.shift tk = @tokens.shift puts "get_tk2 => #{tk.inspect}" if $TOKEN_DEBUG end tk = nil if TkEND_OF_SCRIPT === tk if TkSYMBEG === tk then set_token_position tk.line_no, tk.char_no case tk1 = get_tk when TkId, TkOp, TkSTRING, TkDSTRING, TkSTAR, TkAMPER then if tk1.respond_to?(:name) then tk = Token(TkSYMBOL).set_text(":" + tk1.name) else tk = Token(TkSYMBOL).set_text(":" + tk1.text) end # remove the identifier we just read to replace it with a symbol @token_listeners.each do |obj| obj.pop_token end if @token_listeners else tk = tk1 end end # inform any listeners of our shiny new token @token_listeners.each do |obj| obj.add_token(tk) end if @token_listeners tk end ## # Reads and returns all tokens up to one of +tokens+. Leaves the matched # token in the token list. def get_tk_until(*tokens) read = [] loop do tk = get_tk case tk when *tokens then unget_tk tk break end read << tk end read end ## # Retrieves a String representation of the read tokens def get_tkread read = @read.join("") @read = [] read end ## # Peek equivalent for get_tkread def peek_read @read.join('') end ## # Peek at the next token, but don't remove it from the stream def peek_tk unget_tk(tk = get_tk) tk end ## # Removes the token listener +obj+ def remove_token_listener(obj) @token_listeners.delete(obj) end ## # Resets the tools def reset @read = [] @tokens = [] @unget_read = [] @nest = 0 end ## # Skips whitespace tokens including newlines if +skip_nl+ is true def skip_tkspace(skip_nl = true) # HACK dup tokens = [] while TkSPACE === (tk = get_tk) or (skip_nl and TkNL === tk) do tokens.push tk end unget_tk tk tokens end ## # Has +obj+ listen to tokens def token_listener(obj) add_token_listener obj yield ensure remove_token_listener obj end ## # Returns +tk+ to the scanner def unget_tk(tk) @tokens.unshift tk @unget_read.unshift @read.pop # Remove this token from any listeners @token_listeners.each do |obj| obj.pop_token end if @token_listeners nil end end rdoc/parser/rd.rb000064400000000630147635155430007735 0ustar00## # Parse a RD format file. The parsed RDoc::Markup::Document is attached as a # file comment. class RDoc::Parser::RD < RDoc::Parser include RDoc::Parser::Text parse_files_matching(/\.rd(?:\.[^.]+)?$/) ## # Creates an rd-format TopLevel for the given file. def scan comment = RDoc::Comment.new @content, @top_level comment.format = 'rd' @top_level.comment = comment end end rdoc/parser/ruby.rb000064400000132201147635155430010311 0ustar00## # This file contains stuff stolen outright from: # # rtags.rb - # ruby-lex.rb - ruby lexcal analyzer # ruby-token.rb - ruby tokens # by Keiju ISHITSUKA (Nippon Rational Inc.) # $TOKEN_DEBUG ||= nil ## # Extracts code elements from a source file returning a TopLevel object # containing the constituent file elements. # # This file is based on rtags # # RubyParser understands how to document: # * classes # * modules # * methods # * constants # * aliases # * private, public, protected # * private_class_function, public_class_function # * module_function # * attr, attr_reader, attr_writer, attr_accessor # * extra accessors given on the command line # * metaprogrammed methods # * require # * include # # == Method Arguments # #-- # NOTE: I don't think this works, needs tests, remove the paragraph following # this block when known to work # # The parser extracts the arguments from the method definition. You can # override this with a custom argument definition using the :args: directive: # # ## # # This method tries over and over until it is tired # # def go_go_go(thing_to_try, tries = 10) # :args: thing_to_try # puts thing_to_try # go_go_go thing_to_try, tries - 1 # end # # If you have a more-complex set of overrides you can use the :call-seq: # directive: #++ # # The parser extracts the arguments from the method definition. You can # override this with a custom argument definition using the :call-seq: # directive: # # ## # # This method can be called with a range or an offset and length # # # # :call-seq: # # my_method(Range) # # my_method(offset, length) # # def my_method(*args) # end # # The parser extracts +yield+ expressions from method bodies to gather the # yielded argument names. If your method manually calls a block instead of # yielding or you want to override the discovered argument names use # the :yields: directive: # # ## # # My method is awesome # # def my_method(&block) # :yields: happy, times # block.call 1, 2 # end # # == Metaprogrammed Methods # # To pick up a metaprogrammed method, the parser looks for a comment starting # with '##' before an identifier: # # ## # # This is a meta-programmed method! # # add_my_method :meta_method, :arg1, :arg2 # # The parser looks at the token after the identifier to determine the name, in # this example, :meta_method. If a name cannot be found, a warning is printed # and 'unknown is used. # # You can force the name of a method using the :method: directive: # # ## # # :method: some_method! # # By default, meta-methods are instance methods. To indicate that a method is # a singleton method instead use the :singleton-method: directive: # # ## # # :singleton-method: # # You can also use the :singleton-method: directive with a name: # # ## # # :singleton-method: some_method! # # Additionally you can mark a method as an attribute by # using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like # for :method:, the name is optional. # # ## # # :attr_reader: my_attr_name # # == Hidden methods and attributes # # You can provide documentation for methods that don't appear using # the :method:, :singleton-method: and :attr: directives: # # ## # # :attr_writer: ghost_writer # # There is an attribute here, but you can't see it! # # ## # # :method: ghost_method # # There is a method here, but you can't see it! # # ## # # this is a comment for a regular method # # def regular_method() end # # Note that by default, the :method: directive will be ignored if there is a # standard rdocable item following it. class RDoc::Parser::Ruby < RDoc::Parser parse_files_matching(/\.rbw?$/) include RDoc::RubyToken include RDoc::TokenStream include RDoc::Parser::RubyTools ## # RDoc::NormalClass type NORMAL = "::" ## # RDoc::SingleClass type SINGLE = "<<" ## # Creates a new Ruby parser. def initialize(top_level, file_name, content, options, stats) super @size = 0 @token_listeners = nil @scanner = RDoc::RubyLex.new content, @options @scanner.exception_on_syntax_error = false @prev_seek = nil @markup = @options.markup @encoding = nil @encoding = @options.encoding if Object.const_defined? :Encoding reset end ## # Look for the first comment in a file that isn't a shebang line. def collect_first_comment skip_tkspace comment = '' comment.force_encoding @encoding if @encoding first_line = true tk = get_tk while TkCOMMENT === tk if first_line and tk.text =~ /\A#!/ then skip_tkspace tk = get_tk elsif first_line and tk.text =~ /\A#\s*-\*-/ then first_line = false skip_tkspace tk = get_tk else first_line = false comment << tk.text << "\n" tk = get_tk if TkNL === tk then skip_tkspace false tk = get_tk end end end unget_tk tk new_comment comment end ## # Aborts with +msg+ def error(msg) msg = make_message msg abort msg end ## # Looks for a true or false token. Returns false if TkFALSE or TkNIL are # found. def get_bool skip_tkspace tk = get_tk case tk when TkTRUE true when TkFALSE, TkNIL false else unget_tk tk true end end ## # Look for the name of a class of module (optionally with a leading :: or # with :: separated named) and return the ultimate name, the associated # container, and the given name (with the ::). def get_class_or_module container, ignore_constants = false skip_tkspace name_t = get_tk given_name = '' # class ::A -> A is in the top level case name_t when TkCOLON2, TkCOLON3 then # bug name_t = get_tk container = @top_level given_name << '::' end skip_tkspace false given_name << name_t.name while TkCOLON2 === peek_tk do prev_container = container container = container.find_module_named name_t.name container ||= if ignore_constants then RDoc::Context.new else c = prev_container.add_module RDoc::NormalModule, name_t.name c.ignore unless prev_container.document_children c end container.record_location @top_level get_tk skip_tkspace false name_t = get_tk given_name << '::' << name_t.name end skip_tkspace false return [container, name_t, given_name] end ## # Return a superclass, which can be either a constant of an expression def get_class_specification tk = get_tk return 'self' if TkSELF === tk return '' if TkGVAR === tk res = '' while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do res += tk.name tk = get_tk end unget_tk(tk) skip_tkspace false get_tkread # empty out read buffer tk = get_tk case tk when TkNL, TkCOMMENT, TkSEMICOLON then unget_tk(tk) return res end res += parse_call_parameters(tk) res end ## # Parse a constant, which might be qualified by one or more class or module # names def get_constant res = "" skip_tkspace false tk = get_tk while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do res += tk.name tk = get_tk end # if res.empty? # warn("Unexpected token #{tk} in constant") # end unget_tk(tk) res end ## # Get a constant that may be surrounded by parens def get_constant_with_optional_parens skip_tkspace false nest = 0 while TkLPAREN === (tk = peek_tk) or TkfLPAREN === tk do get_tk skip_tkspace nest += 1 end name = get_constant while nest > 0 skip_tkspace tk = get_tk nest -= 1 if TkRPAREN === tk end name end ## # Extracts a name or symbol from the token stream. def get_symbol_or_name tk = get_tk case tk when TkSYMBOL then text = tk.text.sub(/^:/, '') if TkASSIGN === peek_tk then get_tk text << '=' end text when TkId, TkOp then tk.name when TkAMPER, TkDSTRING, TkSTAR, TkSTRING then tk.text else raise RDoc::Error, "Name or symbol expected (got #{tk})" end end ## # Look for directives in a normal comment block: # # # :stopdoc: # # Don't display comment from this point forward # # This routine modifies its +comment+ parameter. def look_for_directives_in context, comment @preprocess.handle comment, context do |directive, param| case directive when 'method', 'singleton-method', 'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then false # handled elsewhere when 'section' then context.set_current_section param, comment.dup comment.text = '' break end end remove_private_comments comment end ## # Adds useful info about the parser to +message+ def make_message message prefix = "#{@file_name}:" prefix << "#{@scanner.line_no}:#{@scanner.char_no}:" if @scanner "#{prefix} #{message}" end ## # Creates a comment with the correct format def new_comment comment c = RDoc::Comment.new comment, @top_level c.format = @markup c end ## # Creates an RDoc::Attr for the name following +tk+, setting the comment to # +comment+. def parse_attr(context, single, tk, comment) offset = tk.seek line_no = tk.line_no args = parse_symbol_arg 1 if args.size > 0 then name = args[0] rw = "R" skip_tkspace false tk = get_tk if TkCOMMA === tk then rw = "RW" if get_bool else unget_tk tk end att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE att.record_location @top_level att.offset = offset att.line = line_no read_documentation_modifiers att, RDoc::ATTR_MODIFIERS context.add_attribute att @stats.add_attribute att else warn "'attr' ignored - looks like a variable" end end ## # Creates an RDoc::Attr for each attribute listed after +tk+, setting the # comment for each to +comment+. def parse_attr_accessor(context, single, tk, comment) offset = tk.seek line_no = tk.line_no args = parse_symbol_arg rw = "?" tmp = RDoc::CodeObject.new read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS # TODO In most other places we let the context keep track of document_self # and add found items appropriately but here we do not. I'm not sure why. return unless tmp.document_self case tk.name when "attr_reader" then rw = "R" when "attr_writer" then rw = "W" when "attr_accessor" then rw = "RW" else rw = '?' end for name in args att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE att.record_location @top_level att.offset = offset att.line = line_no context.add_attribute att @stats.add_attribute att end end ## # Parses an +alias+ in +context+ with +comment+ def parse_alias(context, single, tk, comment) offset = tk.seek line_no = tk.line_no skip_tkspace if TkLPAREN === peek_tk then get_tk skip_tkspace end new_name = get_symbol_or_name @scanner.instance_eval { @lex_state = EXPR_FNAME } skip_tkspace if TkCOMMA === peek_tk then get_tk skip_tkspace end begin old_name = get_symbol_or_name rescue RDoc::Error return end al = RDoc::Alias.new(get_tkread, old_name, new_name, comment, single == SINGLE) al.record_location @top_level al.offset = offset al.line = line_no read_documentation_modifiers al, RDoc::ATTR_MODIFIERS context.add_alias al @stats.add_alias al al end ## # Extracts call parameters from the token stream. def parse_call_parameters(tk) end_token = case tk when TkLPAREN, TkfLPAREN TkRPAREN when TkRPAREN return "" else TkNL end nest = 0 loop do case tk when TkSEMICOLON break when TkLPAREN, TkfLPAREN nest += 1 when end_token if end_token == TkRPAREN nest -= 1 break if @scanner.lex_state == EXPR_END and nest <= 0 else break unless @scanner.continue end when TkCOMMENT, TkASSIGN, TkOPASGN unget_tk(tk) break when nil then break end tk = get_tk end res = get_tkread.tr("\n", " ").strip res = "" if res == ";" res end ## # Parses a class in +context+ with +comment+ def parse_class container, single, tk, comment offset = tk.seek line_no = tk.line_no declaration_context = container container, name_t, given_name = get_class_or_module container case name_t when TkCONSTANT name = name_t.name superclass = '::Object' if given_name =~ /^::/ then declaration_context = @top_level given_name = $' end if TkLT === peek_tk then get_tk skip_tkspace superclass = get_class_specification superclass = '(unknown)' if superclass.empty? end cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass cls = declaration_context.add_class cls_type, given_name, superclass cls.ignore unless container.document_children read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS cls.record_location @top_level cls.offset = offset cls.line = line_no cls.add_comment comment, @top_level @top_level.add_to_classes_or_modules cls @stats.add_class cls parse_statements cls when TkLSHFT case name = get_class_specification when 'self', container.name parse_statements container, SINGLE else other = @store.find_class_named name unless other then if name =~ /^::/ then name = $' container = @top_level end other = container.add_module RDoc::NormalModule, name other.record_location @top_level other.offset = offset other.line = line_no # class << $gvar other.ignore if name.empty? other.add_comment comment, @top_level end # notify :nodoc: all if not a constant-named class/module # (and remove any comment) unless name =~ /\A(::)?[A-Z]/ then other.document_self = nil other.document_children = false other.clear_comment end @top_level.add_to_classes_or_modules other @stats.add_class other read_documentation_modifiers other, RDoc::CLASS_MODIFIERS parse_statements(other, SINGLE) end else warn("Expected class name or '<<'. Got #{name_t.class}: #{name_t.text.inspect}") end end ## # Parses a constant in +context+ with +comment+. If +ignore_constants+ is # true, no found constants will be added to RDoc. def parse_constant container, tk, comment, ignore_constants = false offset = tk.seek line_no = tk.line_no name = tk.name skip_tkspace false return unless name =~ /^\w+$/ eq_tk = get_tk if TkCOLON2 === eq_tk then unget_tk eq_tk unget_tk tk container, name_t, = get_class_or_module container, ignore_constants name = name_t.name eq_tk = get_tk end unless TkASSIGN === eq_tk then unget_tk eq_tk return false end value = '' con = RDoc::Constant.new name, value, comment nest = 0 get_tkread tk = get_tk if TkGT === tk then unget_tk tk unget_tk eq_tk return false end rhs_name = '' loop do case tk when TkSEMICOLON then break if nest <= 0 when TkLPAREN, TkfLPAREN, TkLBRACE, TkfLBRACE, TkLBRACK, TkfLBRACK, TkDO, TkIF, TkUNLESS, TkCASE, TkDEF, TkBEGIN then nest += 1 when TkRPAREN, TkRBRACE, TkRBRACK, TkEND then nest -= 1 when TkCOMMENT then if nest <= 0 && (@scanner.lex_state == EXPR_END || !@scanner.continue) then unget_tk tk break else unget_tk tk read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS end when TkCONSTANT then rhs_name << tk.name if nest <= 0 and TkNL === peek_tk then mod = if rhs_name =~ /^::/ then @store.find_class_or_module rhs_name else container.find_module_named rhs_name end container.add_module_alias mod, name, @top_level if mod break end when TkNL then if nest <= 0 && (@scanner.lex_state == EXPR_END || !@scanner.continue) then unget_tk tk break end when TkCOLON2, TkCOLON3 then rhs_name << '::' when nil then break end tk = get_tk end res = get_tkread.gsub(/^[ \t]+/, '').strip res = "" if res == ";" value.replace res con.record_location @top_level con.offset = offset con.line = line_no read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS @stats.add_constant con con = container.add_constant con true end ## # Generates an RDoc::Method or RDoc::Attr from +comment+ by looking for # :method: or :attr: directives in +comment+. def parse_comment container, tk, comment return parse_comment_tomdoc container, tk, comment if @markup == 'tomdoc' column = tk.char_no offset = tk.seek line_no = tk.line_no text = comment.text singleton = !!text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3') # REFACTOR if text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then name = $1 unless $1.empty? meth = RDoc::GhostMethod.new get_tkread, name meth.record_location @top_level meth.singleton = singleton meth.offset = offset meth.line = line_no meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * column position_comment = TkCOMMENT.new 0, line_no, 1 position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [position_comment, NEWLINE_TOKEN, indent] meth.params = '' comment.normalize comment.extract_call_seq meth return unless meth.name container.add_method meth meth.comment = comment @stats.add_method meth elsif text.sub!(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then rw = case $1 when 'attr_reader' then 'R' when 'attr_writer' then 'W' else 'RW' end name = $3 unless $3.empty? # TODO authorize 'singleton-attr...'? att = RDoc::Attr.new get_tkread, name, rw, comment att.record_location @top_level att.offset = offset att.line = line_no container.add_attribute att @stats.add_attribute att end true end ## # Creates an RDoc::Method on +container+ from +comment+ if there is a # Signature section in the comment def parse_comment_tomdoc container, tk, comment return unless signature = RDoc::TomDoc.signature(comment) offset = tk.seek line_no = tk.line_no name, = signature.split %r%[ \(]%, 2 meth = RDoc::GhostMethod.new get_tkread, name meth.record_location @top_level meth.offset = offset meth.line = line_no meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * offset position_comment = TkCOMMENT.new 0, line_no, 1 position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [position_comment, NEWLINE_TOKEN, indent] meth.call_seq = signature comment.normalize return unless meth.name container.add_method meth meth.comment = comment @stats.add_method meth end ## # Parses an +include+ in +context+ with +comment+ def parse_include context, comment loop do skip_tkspace_comment name = get_constant_with_optional_parens unless name.empty? then incl = context.add_include RDoc::Include.new(name, comment) incl.record_location @top_level end return unless TkCOMMA === peek_tk get_tk end end ## # Parses an +extend+ in +context+ with +comment+ def parse_extend context, comment loop do skip_tkspace_comment name = get_constant_with_optional_parens unless name.empty? then incl = context.add_extend RDoc::Extend.new(name, comment) incl.record_location @top_level end return unless TkCOMMA === peek_tk get_tk end end ## # Parses a meta-programmed attribute and creates an RDoc::Attr. # # To create foo and bar attributes on class C with comment "My attributes": # # class C # # ## # # :attr: # # # # My attributes # # my_attr :foo, :bar # # end # # To create a foo attribute on class C with comment "My attribute": # # class C # # ## # # :attr: foo # # # # My attribute # # my_attr :foo, :bar # # end def parse_meta_attr(context, single, tk, comment) args = parse_symbol_arg rw = "?" # If nodoc is given, don't document any of them tmp = RDoc::CodeObject.new read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS if comment.text.sub!(/^# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then rw = case $1 when 'attr_reader' then 'R' when 'attr_writer' then 'W' else 'RW' end name = $3 unless $3.empty? end if name then att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE att.record_location @top_level context.add_attribute att @stats.add_attribute att else args.each do |attr_name| att = RDoc::Attr.new(get_tkread, attr_name, rw, comment, single == SINGLE) att.record_location @top_level context.add_attribute att @stats.add_attribute att end end att end ## # Parses a meta-programmed method def parse_meta_method(container, single, tk, comment) column = tk.char_no offset = tk.seek line_no = tk.line_no start_collecting_tokens add_token tk add_token_listener self skip_tkspace false singleton = !!comment.text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3') if comment.text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then name = $1 unless $1.empty? end if name.nil? then name_t = get_tk case name_t when TkSYMBOL then name = name_t.text[1..-1] when TkSTRING then name = name_t.value[1..-2] when TkASSIGN then # ignore remove_token_listener self return else warn "unknown name token #{name_t.inspect} for meta-method '#{tk.name}'" name = 'unknown' end end meth = RDoc::MetaMethod.new get_tkread, name meth.record_location @top_level meth.offset = offset meth.line = line_no meth.singleton = singleton remove_token_listener self meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * column position_comment = TkCOMMENT.new 0, line_no, 1 position_comment.value = "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [position_comment, NEWLINE_TOKEN, indent] meth.add_tokens @token_stream token_listener meth do meth.params = '' comment.normalize comment.extract_call_seq meth container.add_method meth last_tk = tk while tk = get_tk do case tk when TkSEMICOLON then break when TkNL then break unless last_tk and TkCOMMA === last_tk when TkSPACE then # expression continues when TkDO then parse_statements container, single, meth break else last_tk = tk end end end meth.comment = comment @stats.add_method meth meth end ## # Parses a normal method defined by +def+ def parse_method(container, single, tk, comment) added_container = nil meth = nil name = nil column = tk.char_no offset = tk.seek line_no = tk.line_no start_collecting_tokens add_token tk token_listener self do @scanner.instance_eval do @lex_state = EXPR_FNAME end skip_tkspace name_t = get_tk back_tk = skip_tkspace meth = nil added_container = false case dot = get_tk when TkDOT, TkCOLON2 then @scanner.instance_eval do @lex_state = EXPR_FNAME end skip_tkspace name_t2 = get_tk case name_t when TkSELF, TkMOD then name = case name_t2 # NOTE: work around '[' being consumed early and not being # re-tokenized as a TkAREF when TkfLBRACK then get_tk '[]' else name_t2.name end when TkCONSTANT then name = name_t2.name prev_container = container container = container.find_module_named(name_t.name) unless container then constant = prev_container.constants.find do |const| const.name == name_t.name end if constant then parse_method_dummy prev_container return end end unless container then added_container = true obj = name_t.name.split("::").inject(Object) do |state, item| state.const_get(item) end rescue nil type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule unless [Class, Module].include?(obj.class) then warn("Couldn't find #{name_t.name}. Assuming it's a module") end if type == RDoc::NormalClass then sclass = obj.superclass ? obj.superclass.name : nil container = prev_container.add_class type, name_t.name, sclass else container = prev_container.add_module type, name_t.name end container.record_location @top_level end when TkIDENTIFIER, TkIVAR, TkGVAR then parse_method_dummy container return when TkTRUE, TkFALSE, TkNIL then klass_name = "#{name_t.name.capitalize}Class" container = @store.find_class_named klass_name container ||= @top_level.add_class RDoc::NormalClass, klass_name name = name_t2.name else warn "unexpected method name token #{name_t.inspect}" # break skip_method container return end meth = RDoc::AnyMethod.new(get_tkread, name) meth.singleton = true else unget_tk dot back_tk.reverse_each do |token| unget_tk token end name = case name_t when TkSTAR, TkAMPER then name_t.text else unless name_t.respond_to? :name then warn "expected method name token, . or ::, got #{name_t.inspect}" skip_method container return end name_t.name end meth = RDoc::AnyMethod.new get_tkread, name meth.singleton = (single == SINGLE) end end meth.record_location @top_level meth.offset = offset meth.line = line_no meth.start_collecting_tokens indent = TkSPACE.new 0, 1, 1 indent.set_text " " * column token = TkCOMMENT.new 0, line_no, 1 token.set_text "# File #{@top_level.relative_name}, line #{line_no}" meth.add_tokens [token, NEWLINE_TOKEN, indent] meth.add_tokens @token_stream token_listener meth do @scanner.instance_eval do @continue = false end parse_method_parameters meth if meth.document_self then container.add_method meth elsif added_container then container.document_self = false end # Having now read the method parameters and documentation modifiers, we # now know whether we have to rename #initialize to ::new if name == "initialize" && !meth.singleton then if meth.dont_rename_initialize then meth.visibility = :protected else meth.singleton = true meth.name = "new" meth.visibility = :public end end parse_statements container, single, meth end comment.normalize comment.extract_call_seq meth meth.comment = comment @stats.add_method meth end ## # Parses a method that needs to be ignored. def parse_method_dummy container dummy = RDoc::Context.new dummy.parent = container dummy.store = container.store skip_method dummy end ## # Extracts +yield+ parameters from +method+ def parse_method_or_yield_parameters(method = nil, modifiers = RDoc::METHOD_MODIFIERS) skip_tkspace false tk = get_tk # Little hack going on here. In the statement # f = 2*(1+yield) # We see the RPAREN as the next token, so we need # to exit early. This still won't catch all cases # (such as "a = yield + 1" end_token = case tk when TkLPAREN, TkfLPAREN TkRPAREN when TkRPAREN return "" else TkNL end nest = 0 loop do case tk when TkSEMICOLON then break if nest == 0 when TkLBRACE, TkfLBRACE then nest += 1 when TkRBRACE then nest -= 1 if nest <= 0 # we might have a.each { |i| yield i } unget_tk(tk) if nest < 0 break end when TkLPAREN, TkfLPAREN then nest += 1 when end_token then if end_token == TkRPAREN nest -= 1 break if nest <= 0 else break unless @scanner.continue end when TkRPAREN then nest -= 1 when method && method.block_params.nil? && TkCOMMENT then unget_tk tk read_documentation_modifiers method, modifiers @read.pop when TkCOMMENT then @read.pop when nil then break end tk = get_tk end res = get_tkread.gsub(/\s+/, ' ').strip res = '' if res == ';' res end ## # Capture the method's parameters. Along the way, look for a comment # containing: # # # yields: .... # # and add this as the block_params for the method def parse_method_parameters method res = parse_method_or_yield_parameters method res = "(#{res})" unless res =~ /\A\(/ method.params = res unless method.params return if method.block_params skip_tkspace false read_documentation_modifiers method, RDoc::METHOD_MODIFIERS end ## # Parses an RDoc::NormalModule in +container+ with +comment+ def parse_module container, single, tk, comment container, name_t, = get_class_or_module container name = name_t.name mod = container.add_module RDoc::NormalModule, name mod.ignore unless container.document_children mod.record_location @top_level read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS mod.add_comment comment, @top_level parse_statements mod @top_level.add_to_classes_or_modules mod @stats.add_module mod end ## # Parses an RDoc::Require in +context+ containing +comment+ def parse_require(context, comment) skip_tkspace_comment tk = get_tk if TkLPAREN === tk then skip_tkspace_comment tk = get_tk end name = tk.text if TkSTRING === tk if name then @top_level.add_require RDoc::Require.new(name, comment) else unget_tk tk end end ## # Parses a rescue def parse_rescue skip_tkspace false while tk = get_tk case tk when TkNL, TkSEMICOLON then break when TkCOMMA then skip_tkspace false get_tk if TkNL === peek_tk end skip_tkspace false end end ## # The core of the ruby parser. def parse_statements(container, single = NORMAL, current_method = nil, comment = new_comment('')) raise 'no' unless RDoc::Comment === comment comment.force_encoding @encoding if @encoding nest = 1 save_visibility = container.visibility non_comment_seen = true while tk = get_tk do keep_comment = false try_parse_comment = false non_comment_seen = true unless TkCOMMENT === tk case tk when TkNL then skip_tkspace tk = get_tk if TkCOMMENT === tk then if non_comment_seen then # Look for RDoc in a comment about to be thrown away non_comment_seen = parse_comment container, tk, comment unless comment.empty? comment = '' comment.force_encoding @encoding if @encoding end while TkCOMMENT === tk do comment << tk.text << "\n" tk = get_tk if TkNL === tk then skip_tkspace false # leading spaces tk = get_tk end end comment = new_comment comment unless comment.empty? then look_for_directives_in container, comment if container.done_documenting then container.ongoing_visibility = save_visibility end end keep_comment = true else non_comment_seen = true end unget_tk tk keep_comment = true when TkCLASS then parse_class container, single, tk, comment when TkMODULE then parse_module container, single, tk, comment when TkDEF then parse_method container, single, tk, comment when TkCONSTANT then unless parse_constant container, tk, comment, current_method then try_parse_comment = true end when TkALIAS then parse_alias container, single, tk, comment unless current_method when TkYIELD then if current_method.nil? then warn "Warning: yield outside of method" if container.document_self else parse_yield container, single, tk, current_method end # Until and While can have a 'do', which shouldn't increase the nesting. # We can't solve the general case, but we can handle most occurrences by # ignoring a do at the end of a line. when TkUNTIL, TkWHILE then nest += 1 skip_optional_do_after_expression # 'for' is trickier when TkFOR then nest += 1 skip_for_variable skip_optional_do_after_expression when TkCASE, TkDO, TkIF, TkUNLESS, TkBEGIN then nest += 1 when TkSUPER then current_method.calls_super = true if current_method when TkRESCUE then parse_rescue when TkIDENTIFIER then if nest == 1 and current_method.nil? then case tk.name when 'private', 'protected', 'public', 'private_class_method', 'public_class_method', 'module_function' then parse_visibility container, single, tk keep_comment = true when 'attr' then parse_attr container, single, tk, comment when /^attr_(reader|writer|accessor)$/ then parse_attr_accessor container, single, tk, comment when 'alias_method' then parse_alias container, single, tk, comment when 'require', 'include' then # ignore else if comment.text =~ /\A#\#$/ then case comment.text when /^# +:?attr(_reader|_writer|_accessor)?:/ then parse_meta_attr container, single, tk, comment else method = parse_meta_method container, single, tk, comment method.params = container.params if container.params method.block_params = container.block_params if container.block_params end end end end case tk.name when "require" then parse_require container, comment when "include" then parse_include container, comment when "extend" then parse_extend container, comment end when TkEND then nest -= 1 if nest == 0 then read_documentation_modifiers container, RDoc::CLASS_MODIFIERS container.ongoing_visibility = save_visibility parse_comment container, tk, comment unless comment.empty? return end else try_parse_comment = nest == 1 end if try_parse_comment then non_comment_seen = parse_comment container, tk, comment unless comment.empty? keep_comment = false end unless keep_comment then comment = new_comment '' comment.force_encoding @encoding if @encoding container.params = nil container.block_params = nil end begin get_tkread skip_tkspace false end while peek_tk == TkNL end container.params = nil container.block_params = nil end ## # Parse up to +no+ symbol arguments def parse_symbol_arg(no = nil) args = [] skip_tkspace_comment case tk = get_tk when TkLPAREN loop do skip_tkspace_comment if tk1 = parse_symbol_in_arg args.push tk1 break if no and args.size >= no end skip_tkspace_comment case tk2 = get_tk when TkRPAREN break when TkCOMMA else warn("unexpected token: '#{tk2.inspect}'") if $DEBUG_RDOC break end end else unget_tk tk if tk = parse_symbol_in_arg args.push tk return args if no and args.size >= no end loop do skip_tkspace false tk1 = get_tk unless TkCOMMA === tk1 then unget_tk tk1 break end skip_tkspace_comment if tk = parse_symbol_in_arg args.push tk break if no and args.size >= no end end end args end ## # Returns symbol text from the next token def parse_symbol_in_arg case tk = get_tk when TkSYMBOL tk.text.sub(/^:/, '') when TkSTRING eval @read[-1] when TkDSTRING, TkIDENTIFIER then nil # ignore else warn("Expected symbol or string, got #{tk.inspect}") if $DEBUG_RDOC nil end end ## # Parses statements in the top-level +container+ def parse_top_level_statements container comment = collect_first_comment look_for_directives_in container, comment @markup = comment.format # HACK move if to RDoc::Context#comment= container.comment = comment if container.document_self unless comment.empty? parse_statements container, NORMAL, nil, comment end ## # Determines the visibility in +container+ from +tk+ def parse_visibility(container, single, tk) singleton = (single == SINGLE) vis_type = tk.name vis = case vis_type when 'private' then :private when 'protected' then :protected when 'public' then :public when 'private_class_method' then singleton = true :private when 'public_class_method' then singleton = true :public when 'module_function' then singleton = true :public else raise RDoc::Error, "Invalid visibility: #{tk.name}" end skip_tkspace_comment false case peek_tk # Ryan Davis suggested the extension to ignore modifiers, because he # often writes # # protected unless $TESTING # when TkNL, TkUNLESS_MOD, TkIF_MOD, TkSEMICOLON then container.ongoing_visibility = vis else new_methods = [] case vis_type when 'module_function' then args = parse_symbol_arg container.set_visibility_for args, :private, false container.methods_matching args do |m| s_m = m.dup s_m.record_location @top_level s_m.singleton = true new_methods << s_m end when 'public_class_method', 'private_class_method' then args = parse_symbol_arg container.methods_matching args, true do |m| if m.parent != container then m = m.dup m.record_location @top_level new_methods << m end m.visibility = vis end else args = parse_symbol_arg container.set_visibility_for args, vis, singleton end new_methods.each do |method| case method when RDoc::AnyMethod then container.add_method method when RDoc::Attr then container.add_attribute method end method.visibility = vis end end end ## # Determines the block parameter for +context+ def parse_yield(context, single, tk, method) return if method.block_params get_tkread @scanner.instance_eval { @continue = false } method.block_params = parse_method_or_yield_parameters end ## # Directives are modifier comments that can appear after class, module, or # method names. For example: # # def fred # :yields: a, b # # or: # # class MyClass # :nodoc: # # We return the directive name and any parameters as a two element array if # the name is in +allowed+. A directive can be found anywhere up to the end # of the current line. def read_directive allowed tokens = [] while tk = get_tk do tokens << tk case tk when TkNL then return when TkCOMMENT then return unless tk.text =~ /\s*:?([\w-]+):\s*(.*)/ directive = $1.downcase return [directive, $2] if allowed.include? directive return end end ensure unless tokens.length == 1 and TkCOMMENT === tokens.first then tokens.reverse_each do |token| unget_tk token end end end ## # Handles directives following the definition for +context+ (any # RDoc::CodeObject) if the directives are +allowed+ at this point. # # See also RDoc::Markup::PreProcess#handle_directive def read_documentation_modifiers context, allowed directive, value = read_directive allowed return unless directive @preprocess.handle_directive '', directive, value, context do |dir, param| if %w[notnew not_new not-new].include? dir then context.dont_rename_initialize = true true end end end ## # Removes private comments from +comment+ #-- # TODO remove def remove_private_comments comment comment.remove_private end ## # Scans this ruby file for ruby constructs def scan reset catch :eof do begin parse_top_level_statements @top_level rescue StandardError => e bytes = '' 20.times do @scanner.ungetc end count = 0 60.times do |i| count = i byte = @scanner.getc break unless byte bytes << byte end count -= 20 count.times do @scanner.ungetc end $stderr.puts <<-EOF #{self.class} failure around line #{@scanner.line_no} of #{@file_name} EOF unless bytes.empty? then $stderr.puts $stderr.puts bytes.inspect end raise e end end @top_level end ## # while, until, and for have an optional do def skip_optional_do_after_expression skip_tkspace false tk = get_tk case tk when TkLPAREN, TkfLPAREN then end_token = TkRPAREN else end_token = TkNL end b_nest = 0 nest = 0 @scanner.instance_eval { @continue = false } loop do case tk when TkSEMICOLON then break if b_nest.zero? when TkLPAREN, TkfLPAREN then nest += 1 when TkBEGIN then b_nest += 1 when TkEND then b_nest -= 1 when TkDO break if nest.zero? when end_token then if end_token == TkRPAREN nest -= 1 break if @scanner.lex_state == EXPR_END and nest.zero? else break unless @scanner.continue end when nil then break end tk = get_tk end skip_tkspace false get_tk if TkDO === peek_tk end ## # skip the var [in] part of a 'for' statement def skip_for_variable skip_tkspace false tk = get_tk skip_tkspace false tk = get_tk unget_tk(tk) unless TkIN === tk end ## # Skips the next method in +container+ def skip_method container meth = RDoc::AnyMethod.new "", "anon" parse_method_parameters meth parse_statements container, false, meth end ## # Skip spaces until a comment is found def skip_tkspace_comment(skip_nl = true) loop do skip_tkspace skip_nl return unless TkCOMMENT === peek_tk get_tk end end ## # Prints +message+ to +$stderr+ unless we're being quiet def warn message @options.warn make_message message end end rdoc/parser/changelog.rb000064400000011054147635155430011261 0ustar00require 'time' ## # A ChangeLog file parser. # # This parser converts a ChangeLog into an RDoc::Markup::Document. When # viewed as HTML a ChangeLog page will have an entry for each day's entries in # the sidebar table of contents. # # This parser is meant to parse the MRI ChangeLog, but can be used to parse any # {GNU style Change # Log}[http://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html]. class RDoc::Parser::ChangeLog < RDoc::Parser include RDoc::Parser::Text parse_files_matching(/(\/|\\|\A)ChangeLog[^\/\\]*\z/) ## # Attaches the +continuation+ of the previous line to the +entry_body+. # # Continued function listings are joined together as a single entry. # Continued descriptions are joined to make a single paragraph. def continue_entry_body entry_body, continuation return unless last = entry_body.last if last =~ /\)\s*\z/ and continuation =~ /\A\(/ then last.sub!(/\)\s*\z/, ',') continuation.sub!(/\A\(/, '') end if last =~ /\s\z/ then last << continuation else last << ' ' << continuation end end ## # Creates an RDoc::Markup::Document given the +groups+ of ChangeLog entries. def create_document groups doc = RDoc::Markup::Document.new doc.omit_headings_below = 2 doc.file = @top_level doc << RDoc::Markup::Heading.new(1, File.basename(@file_name)) doc << RDoc::Markup::BlankLine.new groups.sort_by do |day,| day end.reverse_each do |day, entries| doc << RDoc::Markup::Heading.new(2, day.dup) doc << RDoc::Markup::BlankLine.new doc.concat create_entries entries end doc end ## # Returns a list of ChangeLog entries an RDoc::Markup nodes for the given # +entries+. def create_entries entries out = [] entries.each do |entry, items| out << RDoc::Markup::Heading.new(3, entry) out << RDoc::Markup::BlankLine.new out << create_items(items) end out end ## # Returns an RDoc::Markup::List containing the given +items+ in the # ChangeLog def create_items items list = RDoc::Markup::List.new :NOTE items.each do |item| item =~ /\A(.*?(?:\([^)]+\))?):\s*/ title = $1 body = $' paragraph = RDoc::Markup::Paragraph.new body list_item = RDoc::Markup::ListItem.new title, paragraph list << list_item end list end ## # Groups +entries+ by date. def group_entries entries entries.group_by do |title, _| begin Time.parse(title).strftime '%Y-%m-%d' rescue NoMethodError, ArgumentError time, = title.split ' ', 2 Time.parse(time).strftime '%Y-%m-%d' end end end ## # Parses the entries in the ChangeLog. # # Returns an Array of each ChangeLog entry in order of parsing. # # A ChangeLog entry is an Array containing the ChangeLog title (date and # committer) and an Array of ChangeLog items (file and function changed with # description). # # An example result would be: # # [ 'Tue Dec 4 08:33:46 2012 Eric Hodel ', # [ 'README.EXT: Converted to RDoc format', # 'README.EXT.ja: ditto']] def parse_entries entries = [] entry_name = nil entry_body = [] @content.each_line do |line| case line when /^\s*$/ then next when /^\w.*/ then entries << [entry_name, entry_body] if entry_name entry_name = $& begin time = Time.parse entry_name # HACK Ruby 1.8 does not raise ArgumentError for Time.parse "Other" entry_name = nil unless entry_name =~ /#{time.year}/ rescue NoMethodError time, = entry_name.split ' ', 2 time = Time.parse time rescue ArgumentError entry_name = nil end entry_body = [] when /^(\t| {8})?\*\s*(.*)/ then # "\t* file.c (func): ..." entry_body << $2 when /^(\t| {8})?\s*(\(.*)/ then # "\t(func): ..." entry = $2 if entry_body.last =~ /:/ then entry_body << entry else continue_entry_body entry_body, entry end when /^(\t| {8})?\s*(.*)/ then continue_entry_body entry_body, $2 end end entries << [entry_name, entry_body] if entry_name entries.reject! do |(entry,_)| entry == nil end entries end ## # Converts the ChangeLog into an RDoc::Markup::Document def scan entries = parse_entries grouped_entries = group_entries entries doc = create_document grouped_entries @top_level.comment = doc @top_level end end rdoc/parser/markdown.rb000064400000000674147635155430011162 0ustar00## # Parse a Markdown format file. The parsed RDoc::Markup::Document is attached # as a file comment. class RDoc::Parser::Markdown < RDoc::Parser include RDoc::Parser::Text parse_files_matching(/\.(md|markdown)(?:\.[^.]+)?$/) ## # Creates an Markdown-format TopLevel for the given file. def scan comment = RDoc::Comment.new @content, @top_level comment.format = 'markdown' @top_level.comment = comment end end rdoc/parser/c.rb000064400000102647147635155430007565 0ustar00require 'tsort' ## # RDoc::Parser::C attempts to parse C extension files. It looks for # the standard patterns that you find in extensions: rb_define_class, # rb_define_method and so on. It tries to find the corresponding # C source for the methods and extract comments, but if we fail # we don't worry too much. # # The comments associated with a Ruby method are extracted from the C # comment block associated with the routine that _implements_ that # method, that is to say the method whose name is given in the # rb_define_method call. For example, you might write: # # /* # * Returns a new array that is a one-dimensional flattening of this # * array (recursively). That is, for every element that is an array, # * extract its elements into the new array. # * # * s = [ 1, 2, 3 ] #=> [1, 2, 3] # * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] # * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] # * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # */ # static VALUE # rb_ary_flatten(ary) # VALUE ary; # { # ary = rb_obj_dup(ary); # rb_ary_flatten_bang(ary); # return ary; # } # # ... # # void # Init_Array() # { # ... # rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0); # # Here RDoc will determine from the rb_define_method line that there's a # method called "flatten" in class Array, and will look for the implementation # in the method rb_ary_flatten. It will then use the comment from that # method in the HTML output. This method must be in the same source file # as the rb_define_method. # # The comment blocks may include special directives: # # [Document-class: +name+] # Documentation for the named class. # # [Document-module: +name+] # Documentation for the named module. # # [Document-const: +name+] # Documentation for the named +rb_define_const+. # # Constant values can be supplied on the first line of the comment like so: # # /* 300: The highest possible score in bowling */ # rb_define_const(cFoo, "PERFECT", INT2FIX(300)); # # The value can contain internal colons so long as they are escaped with a \ # # [Document-global: +name+] # Documentation for the named +rb_define_global_const+ # # [Document-variable: +name+] # Documentation for the named +rb_define_variable+ # # [Document-method: +method_name+] # Documentation for the named method. Use this when the method name is # unambiguous. # # [Document-method: ClassName::method_name] # Documentation for a singleton method in the given class. Use this when # the method name alone is ambiguous. # # [Document-method: ClassName#method_name] # Documentation for a instance method in the given class. Use this when the # method name alone is ambiguous. # # [Document-attr: +name+] # Documentation for the named attribute. # # [call-seq: text up to an empty line] # Because C source doesn't give descriptive names to Ruby-level parameters, # you need to document the calling sequence explicitly # # In addition, RDoc assumes by default that the C method implementing a # Ruby function is in the same source file as the rb_define_method call. # If this isn't the case, add the comment: # # rb_define_method(....); // in filename # # As an example, we might have an extension that defines multiple classes # in its Init_xxx method. We could document them using # # /* # * Document-class: MyClass # * # * Encapsulate the writing and reading of the configuration # * file. ... # */ # # /* # * Document-method: read_value # * # * call-seq: # * cfg.read_value(key) -> value # * cfg.read_value(key} { |key| } -> value # * # * Return the value corresponding to +key+ from the configuration. # * In the second form, if the key isn't found, invoke the # * block and return its value. # */ class RDoc::Parser::C < RDoc::Parser parse_files_matching(/\.(?:([CcHh])\1?|c([+xp])\2|y)\z/) include RDoc::Text ## # Maps C variable names to names of ruby classes or modules attr_reader :classes ## # C file the parser is parsing attr_accessor :content ## # Dependencies from a missing enclosing class to the classes in # missing_dependencies that depend upon it. attr_reader :enclosure_dependencies ## # Maps C variable names to names of ruby classes (and singleton classes) attr_reader :known_classes ## # Classes found while parsing the C file that were not yet registered due to # a missing enclosing class. These are processed by do_missing attr_reader :missing_dependencies ## # Maps C variable names to names of ruby singleton classes attr_reader :singleton_classes ## # The TopLevel items in the parsed file belong to attr_reader :top_level ## # Prepares for parsing a C file. See RDoc::Parser#initialize for details on # the arguments. def initialize top_level, file_name, content, options, stats super @known_classes = RDoc::KNOWN_CLASSES.dup @content = handle_tab_width handle_ifdefs_in @content @file_dir = File.dirname @file_name @classes = load_variable_map :c_class_variables @singleton_classes = load_variable_map :c_singleton_class_variables # missing variable => [handle_class_module arguments] @missing_dependencies = {} # missing enclosure variable => [dependent handle_class_module arguments] @enclosure_dependencies = Hash.new { |h, k| h[k] = [] } @enclosure_dependencies.instance_variable_set :@missing_dependencies, @missing_dependencies @enclosure_dependencies.extend TSort def @enclosure_dependencies.tsort_each_node &block each_key(&block) rescue TSort::Cyclic => e cycle_vars = e.message.scan(/"(.*?)"/).flatten cycle = cycle_vars.sort.map do |var_name| delete var_name var_name, type, mod_name, = @missing_dependencies[var_name] "#{type} #{mod_name} (#{var_name})" end.join ', ' warn "Unable to create #{cycle} due to a cyclic class or module creation" retry end def @enclosure_dependencies.tsort_each_child node, &block fetch(node, []).each(&block) end end ## # Scans #content for rb_define_alias def do_aliases @content.scan(/rb_define_alias\s*\( \s*(\w+), \s*"(.+?)", \s*"(.+?)" \s*\)/xm) do |var_name, new_name, old_name| class_name = @known_classes[var_name] unless class_name then @options.warn "Enclosing class or module %p for alias %s %s is not known" % [ var_name, new_name, old_name] next end class_obj = find_class var_name, class_name al = RDoc::Alias.new '', old_name, new_name, '' al.singleton = @singleton_classes.key? var_name comment = find_alias_comment var_name, new_name, old_name comment.normalize al.comment = comment al.record_location @top_level class_obj.add_alias al @stats.add_alias al end end ## # Scans #content for rb_attr and rb_define_attr def do_attrs @content.scan(/rb_attr\s*\( \s*(\w+), \s*([\w"()]+), \s*([01]), \s*([01]), \s*\w+\);/xm) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end @content.scan(%r%rb_define_attr\( \s*([\w\.]+), \s*"([^"]+)", \s*(\d+), \s*(\d+)\s*\); %xm) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end end ## # Scans #content for boot_defclass def do_boot_defclass @content.scan(/(\w+)\s*=\s*boot_defclass\s*\(\s*"(\w+?)",\s*(\w+?)\s*\)/) do |var_name, class_name, parent| parent = nil if parent == "0" handle_class_module(var_name, :class, class_name, parent, nil) end end ## # Scans #content for rb_define_class, boot_defclass, rb_define_class_under # and rb_singleton_class def do_classes do_boot_defclass do_define_class do_define_class_under do_singleton_class do_struct_define_without_accessor end ## # Scans #content for rb_define_variable, rb_define_readonly_variable, # rb_define_const and rb_define_global_const def do_constants @content.scan(%r%\Wrb_define_ ( variable | readonly_variable | const | global_const ) \s*\( (?:\s*(\w+),)? \s*"(\w+)", \s*(.*?)\s*\)\s*; %xm) do |type, var_name, const_name, definition| var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel" handle_constants type, var_name, const_name, definition end @content.scan(%r% \Wrb_curses_define_const \s*\( \s* (\w+) \s* \) \s*;%xm) do |consts| const = consts.first handle_constants 'const', 'mCurses', const, "UINT2NUM(#{const})" end @content.scan(%r% \Wrb_file_const \s*\( \s* "([^"]+)", \s* (.*?) \s* \) \s*;%xm) do |name, value| handle_constants 'const', 'rb_mFConst', name, value end end ## # Scans #content for rb_define_class def do_define_class # The '.' lets us handle SWIG-generated files @content.scan(/([\w\.]+)\s* = \s*rb_define_class\s* \( \s*"(\w+)", \s*(\w+)\s* \)/mx) do |var_name, class_name, parent| handle_class_module(var_name, :class, class_name, parent, nil) end end ## # Scans #content for rb_define_class_under def do_define_class_under @content.scan(/([\w\.]+)\s* = # var_name \s*rb_define_class_under\s* \( \s* (\w+), # under \s* "(\w+)", # class_name \s* (?: ([\w\*\s\(\)\.\->]+) | # parent_name rb_path2class\("([\w:]+)"\) # path ) \s* \) /mx) do |var_name, under, class_name, parent_name, path| parent = path || parent_name handle_class_module var_name, :class, class_name, parent, under end end ## # Scans #content for rb_define_module def do_define_module @content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do |var_name, class_name| handle_class_module(var_name, :module, class_name, nil, nil) end end ## # Scans #content for rb_define_module_under def do_define_module_under @content.scan(/(\w+)\s* = \s*rb_define_module_under\s* \( \s*(\w+), \s*"(\w+)" \s*\)/mx) do |var_name, in_module, class_name| handle_class_module(var_name, :module, class_name, nil, in_module) end end ## # Scans #content for rb_include_module def do_includes @content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m| next unless cls = @classes[c] m = @known_classes[m] || m comment = RDoc::Comment.new '', @top_level incl = cls.add_include RDoc::Include.new(m, comment) incl.record_location @top_level end end ## # Scans #content for rb_define_method, rb_define_singleton_method, # rb_define_module_function, rb_define_private_method, # rb_define_global_function and define_filetest_function def do_methods @content.scan(%r%rb_define_ ( singleton_method | method | module_function | private_method ) \s*\(\s*([\w\.]+), \s*"([^"]+)", \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?, \s*(-?\w+)\s*\) (?:;\s*/[*/]\s+in\s+(\w+?\.(?:cpp|c|y)))? %xm) do |type, var_name, meth_name, function, param_count, source_file| # Ignore top-object and weird struct.c dynamic stuff next if var_name == "ruby_top_self" next if var_name == "nstr" var_name = "rb_cObject" if var_name == "rb_mKernel" handle_method(type, var_name, meth_name, function, param_count, source_file) end @content.scan(%r%rb_define_global_function\s*\( \s*"([^"]+)", \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?, \s*(-?\w+)\s*\) (?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))? %xm) do |meth_name, function, param_count, source_file| handle_method("method", "rb_mKernel", meth_name, function, param_count, source_file) end @content.scan(/define_filetest_function\s*\( \s*"([^"]+)", \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?, \s*(-?\w+)\s*\)/xm) do |meth_name, function, param_count| handle_method("method", "rb_mFileTest", meth_name, function, param_count) handle_method("singleton_method", "rb_cFile", meth_name, function, param_count) end end ## # Creates classes and module that were missing were defined due to the file # order being different than the declaration order. def do_missing return if @missing_dependencies.empty? @enclosure_dependencies.tsort.each do |in_module| arguments = @missing_dependencies.delete in_module next unless arguments # dependency on existing class handle_class_module(*arguments) end end ## # Scans #content for rb_define_module and rb_define_module_under def do_modules do_define_module do_define_module_under end ## # Scans #content for rb_singleton_class def do_singleton_class @content.scan(/([\w\.]+)\s* = \s*rb_singleton_class\s* \( \s*(\w+) \s*\)/mx) do |sclass_var, class_var| handle_singleton sclass_var, class_var end end ## # Scans #content for struct_define_without_accessor def do_struct_define_without_accessor @content.scan(/([\w\.]+)\s* = \s*rb_struct_define_without_accessor\s* \( \s*"(\w+)", # Class name \s*(\w+), # Parent class \s*\w+, # Allocation function (\s*"\w+",)* # Attributes \s*NULL \)/mx) do |var_name, class_name, parent| handle_class_module(var_name, :class, class_name, parent, nil) end end ## # Finds the comment for an alias on +class_name+ from +new_name+ to # +old_name+ def find_alias_comment class_name, new_name, old_name content =~ %r%((?>/\*.*?\*/\s+)) rb_define_alias\(\s*#{Regexp.escape class_name}\s*, \s*"#{Regexp.escape new_name}"\s*, \s*"#{Regexp.escape old_name}"\s*\);%xm RDoc::Comment.new($1 || '', @top_level) end ## # Finds a comment for rb_define_attr, rb_attr or Document-attr. # # +var_name+ is the C class variable the attribute is defined on. # +attr_name+ is the attribute's name. # # +read+ and +write+ are the read/write flags ('1' or '0'). Either both or # neither must be provided. def find_attr_comment var_name, attr_name, read = nil, write = nil attr_name = Regexp.escape attr_name rw = if read and write then /\s*#{read}\s*,\s*#{write}\s*/xm else /.*?/m end comment = if @content =~ %r%((?>/\*.*?\*/\s+)) rb_define_attr\((?:\s*#{var_name},)?\s* "#{attr_name}"\s*, #{rw}\)\s*;%xm then $1 elsif @content =~ %r%((?>/\*.*?\*/\s+)) rb_attr\(\s*#{var_name}\s*, \s*#{attr_name}\s*, #{rw},.*?\)\s*;%xm then $1 elsif @content =~ %r%Document-attr:\s#{attr_name}\s*?\n ((?>.*?\*/))%xm then $1 else '' end RDoc::Comment.new comment, @top_level end ## # Find the C code corresponding to a Ruby method def find_body class_name, meth_name, meth_obj, file_content, quiet = false case file_content when %r%((?>/\*.*?\*/\s*)?) ((?:(?:static|SWIGINTERN)\s+)? (?:intern\s+)?VALUE\s+#{meth_name} \s*(\([^)]*\))([^;]|$))%xm then comment = RDoc::Comment.new $1, @top_level body = $2 offset, = $~.offset(2) comment.remove_private if comment # try to find the whole body body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content # The comment block may have been overridden with a 'Document-method' # block. This happens in the interpreter when multiple methods are # vectored through to the same C method but those methods are logically # distinct (for example Kernel.hash and Kernel.object_id share the same # implementation override_comment = find_override_comment class_name, meth_obj comment = override_comment if override_comment comment.normalize find_modifiers comment, meth_obj if comment #meth_obj.params = params meth_obj.start_collecting_tokens tk = RDoc::RubyToken::Token.new nil, 1, 1 tk.set_text body meth_obj.add_token tk meth_obj.comment = comment meth_obj.offset = offset meth_obj.line = file_content[0, offset].count("\n") + 1 body when %r%((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))%m then comment = RDoc::Comment.new $1, @top_level body = $2 offset = $~.offset(2).first find_body class_name, $3, meth_obj, file_content, true comment.normalize find_modifiers comment, meth_obj meth_obj.start_collecting_tokens tk = RDoc::RubyToken::Token.new nil, 1, 1 tk.set_text body meth_obj.add_token tk meth_obj.comment = comment meth_obj.offset = offset meth_obj.line = file_content[0, offset].count("\n") + 1 body when %r%^\s*\#\s*define\s+#{meth_name}\s+(\w+)%m then # with no comment we hope the aliased definition has it and use it's # definition body = find_body(class_name, $1, meth_obj, file_content, true) return body if body @options.warn "No definition for #{meth_name}" false else # No body, but might still have an override comment comment = find_override_comment class_name, meth_obj if comment then comment.normalize find_modifiers comment, meth_obj meth_obj.comment = comment '' else @options.warn "No definition for #{meth_name}" false end end end ## # Finds a RDoc::NormalClass or RDoc::NormalModule for +raw_name+ def find_class(raw_name, name) unless @classes[raw_name] if raw_name =~ /^rb_m/ container = @top_level.add_module RDoc::NormalModule, name else container = @top_level.add_class RDoc::NormalClass, name end container.record_location @top_level @classes[raw_name] = container end @classes[raw_name] end ## # Look for class or module documentation above Init_+class_name+(void), # in a Document-class +class_name+ (or module) comment or above an # rb_define_class (or module). If a comment is supplied above a matching # Init_ and a rb_define_class the Init_ comment is used. # # /* # * This is a comment for Foo # */ # Init_Foo(void) { # VALUE cFoo = rb_define_class("Foo", rb_cObject); # } # # /* # * Document-class: Foo # * This is a comment for Foo # */ # Init_foo(void) { # VALUE cFoo = rb_define_class("Foo", rb_cObject); # } # # /* # * This is a comment for Foo # */ # VALUE cFoo = rb_define_class("Foo", rb_cObject); def find_class_comment class_name, class_mod comment = nil if @content =~ %r% ((?>/\*.*?\*/\s+)) (static\s+)? void\s+ Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xmi then comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '') elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*? (?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then comment = "/*\n#{$1}" elsif @content =~ %r%.*((?>/\*.*?\*/\s+)) ([\w\.\s]+\s* = \s+)?rb_define_(class|module).*?"(#{class_name})"%xm then comment = $1 elsif @content =~ %r%.*((?>/\*.*?\*/\s+)) ([\w\.\s]+\s* = \s+)?rb_define_(class|module)_under.*?"(#{class_name.split('::').last})"%xm then comment = $1 else comment = '' end comment = RDoc::Comment.new comment, @top_level comment.normalize look_for_directives_in class_mod, comment class_mod.add_comment comment, @top_level end ## # Finds a comment matching +type+ and +const_name+ either above the # comment or in the matching Document- section. def find_const_comment(type, const_name, class_name = nil) comment = if @content =~ %r%((?>^\s*/\*.*?\*/\s+)) rb_define_#{type}\((?:\s*(\w+),)?\s* "#{const_name}"\s*, .*?\)\s*;%xmi then $1 elsif class_name and @content =~ %r%Document-(?:const|global|variable):\s #{class_name}::#{const_name} \s*?\n((?>.*?\*/))%xm then "/*\n#{$1}" elsif @content =~ %r%Document-(?:const|global|variable): \s#{const_name} \s*?\n((?>.*?\*/))%xm then "/*\n#{$1}" else '' end RDoc::Comment.new comment, @top_level end ## # Handles modifiers in +comment+ and updates +meth_obj+ as appropriate. def find_modifiers comment, meth_obj comment.normalize comment.extract_call_seq meth_obj look_for_directives_in meth_obj, comment end ## # Finds a Document-method override for +meth_obj+ on +class_name+ def find_override_comment class_name, meth_obj name = Regexp.escape meth_obj.name prefix = Regexp.escape meth_obj.name_prefix comment = if @content =~ %r%Document-method: \s+#{class_name}#{prefix}#{name} \s*?\n((?>.*?\*/))%xm then "/*#{$1}" elsif @content =~ %r%Document-method: \s#{name}\s*?\n((?>.*?\*/))%xm then "/*#{$1}" end return unless comment RDoc::Comment.new comment, @top_level end ## # Creates a new RDoc::Attr +attr_name+ on class +var_name+ that is either # +read+, +write+ or both def handle_attr(var_name, attr_name, read, write) rw = '' rw << 'R' if '1' == read rw << 'W' if '1' == write class_name = @known_classes[var_name] return unless class_name class_obj = find_class var_name, class_name return unless class_obj comment = find_attr_comment var_name, attr_name comment.normalize name = attr_name.gsub(/rb_intern\("([^"]+)"\)/, '\1') attr = RDoc::Attr.new '', name, rw, comment attr.record_location @top_level class_obj.add_attribute attr @stats.add_attribute attr end ## # Creates a new RDoc::NormalClass or RDoc::NormalModule based on +type+ # named +class_name+ in +parent+ which was assigned to the C +var_name+. def handle_class_module(var_name, type, class_name, parent, in_module) parent_name = @known_classes[parent] || parent if in_module then enclosure = @classes[in_module] || @store.find_c_enclosure(in_module) if enclosure.nil? and enclosure = @known_classes[in_module] then enc_type = /^rb_m/ =~ in_module ? :module : :class handle_class_module in_module, enc_type, enclosure, nil, nil enclosure = @classes[in_module] end unless enclosure then @enclosure_dependencies[in_module] << var_name @missing_dependencies[var_name] = [var_name, type, class_name, parent, in_module] return end else enclosure = @top_level end if type == :class then full_name = if RDoc::ClassModule === enclosure then enclosure.full_name + "::#{class_name}" else class_name end if @content =~ %r%Document-class:\s+#{full_name}\s*<\s+([:,\w]+)% then parent_name = $1 end cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name else cm = enclosure.add_module RDoc::NormalModule, class_name end cm.record_location enclosure.top_level find_class_comment cm.full_name, cm case cm when RDoc::NormalClass @stats.add_class cm when RDoc::NormalModule @stats.add_module cm end @classes[var_name] = cm @known_classes[var_name] = cm.full_name @store.add_c_enclosure var_name, cm end ## # Adds constants. By providing some_value: at the start of the comment you # can override the C value of the comment to give a friendly definition. # # /* 300: The perfect score in bowling */ # rb_define_const(cFoo, "PERFECT", INT2FIX(300); # # Will override INT2FIX(300) with the value +300+ in the output # RDoc. Values may include quotes and escaped colons (\:). def handle_constants(type, var_name, const_name, definition) class_name = @known_classes[var_name] return unless class_name class_obj = find_class var_name, class_name unless class_obj then @options.warn 'Enclosing class or module %p is not known' % [const_name] return end comment = find_const_comment type, const_name, class_name comment.normalize # In the case of rb_define_const, the definition and comment are in # "/* definition: comment */" form. The literal ':' and '\' characters # can be escaped with a backslash. if type.downcase == 'const' then no_match, new_definition, new_comment = comment.text.split(/(\A.*):/) if no_match and no_match.empty? then if new_definition.empty? then # Default to literal C definition new_definition = definition else new_definition.gsub!("\:", ":") new_definition.gsub!("\\", '\\') end new_definition.sub!(/\A(\s+)/, '') new_comment = "#{$1}#{new_comment.lstrip}" new_comment = RDoc::Comment.new new_comment, @top_level con = RDoc::Constant.new const_name, new_definition, new_comment else con = RDoc::Constant.new const_name, definition, comment end else con = RDoc::Constant.new const_name, definition, comment end con.record_location @top_level @stats.add_constant con class_obj.add_constant con end ## # Removes #ifdefs that would otherwise confuse us def handle_ifdefs_in(body) body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m, '\1') end ## # Adds an RDoc::AnyMethod +meth_name+ defined on a class or module assigned # to +var_name+. +type+ is the type of method definition function used. # +singleton_method+ and +module_function+ create a singleton method. def handle_method(type, var_name, meth_name, function, param_count, source_file = nil) class_name = @known_classes[var_name] singleton = @singleton_classes.key? var_name return unless class_name class_obj = find_class var_name, class_name if class_obj then if meth_name == 'initialize' then meth_name = 'new' singleton = true type = 'method' # force public end meth_obj = RDoc::AnyMethod.new '', meth_name meth_obj.c_function = function meth_obj.singleton = singleton || %w[singleton_method module_function].include?(type) p_count = Integer(param_count) rescue -1 if source_file then file_name = File.join @file_dir, source_file if File.exist? file_name then file_content = File.read file_name else @options.warn "unknown source #{source_file} for #{meth_name} in #{@file_name}" end else file_content = @content end body = find_body class_name, function, meth_obj, file_content if body and meth_obj.document_self then meth_obj.params = if p_count < -1 then # -2 is Array '(*args)' elsif p_count == -1 then # argc, argv rb_scan_args body else "(#{(1..p_count).map { |i| "p#{i}" }.join ', '})" end meth_obj.record_location @top_level class_obj.add_method meth_obj @stats.add_method meth_obj meth_obj.visibility = :private if 'private_method' == type end end end ## # Registers a singleton class +sclass_var+ as a singleton of +class_var+ def handle_singleton sclass_var, class_var class_name = @known_classes[class_var] @known_classes[sclass_var] = class_name @singleton_classes[sclass_var] = class_name end ## # Normalizes tabs in +body+ def handle_tab_width(body) if /\t/ =~ body tab_width = @options.tab_width body.split(/\n/).map do |line| 1 while line.gsub!(/\t+/) do ' ' * (tab_width * $&.length - $`.length % tab_width) end && $~ line end.join "\n" else body end end ## # Loads the variable map with the given +name+ from the RDoc::Store, if # present. def load_variable_map map_name return {} unless files = @store.cache[map_name] return {} unless name_map = files[@file_name] class_map = {} name_map.each do |variable, name| next unless mod = @store.find_class_or_module(name) class_map[variable] = if map_name == :c_class_variables then mod else name end @known_classes[variable] = name end class_map end ## # Look for directives in a normal comment block: # # /* # * :title: My Awesome Project # */ # # This method modifies the +comment+ def look_for_directives_in context, comment @preprocess.handle comment, context do |directive, param| case directive when 'main' then @options.main_page = param '' when 'title' then @options.default_title = param if @options.respond_to? :default_title= '' end end comment end ## # Extracts parameters from the +method_body+ and returns a method # parameter string. Follows 1.9.3dev's scan-arg-spec, see README.EXT def rb_scan_args method_body method_body =~ /rb_scan_args\((.*?)\)/m return '(*args)' unless $1 $1.split(/,/)[2] =~ /"(.*?)"/ # format argument format = $1.split(//) lead = opt = trail = 0 if format.first =~ /\d/ then lead = $&.to_i format.shift if format.first =~ /\d/ then opt = $&.to_i format.shift if format.first =~ /\d/ then trail = $&.to_i format.shift block_arg = true end end end if format.first == '*' and not block_arg then var = true format.shift if format.first =~ /\d/ then trail = $&.to_i format.shift end end if format.first == ':' then hash = true format.shift end if format.first == '&' then block = true format.shift end # if the format string is not empty there's a bug in the C code, ignore it args = [] position = 1 (1...(position + lead)).each do |index| args << "p#{index}" end position += lead (position...(position + opt)).each do |index| args << "p#{index} = v#{index}" end position += opt if var then args << '*args' position += 1 end (position...(position + trail)).each do |index| args << "p#{index}" end position += trail if hash then args << "p#{position} = {}" position += 1 end args << '&block' if block "(#{args.join ', '})" end ## # Removes lines that are commented out that might otherwise get picked up # when scanning for classes and methods def remove_commented_out_lines @content.gsub!(%r%//.*rb_define_%, '//') end ## # Extracts the classes, modules, methods, attributes, constants and aliases # from a C file and returns an RDoc::TopLevel for this file def scan remove_commented_out_lines do_modules do_classes do_missing do_constants do_methods do_includes do_aliases do_attrs @store.add_c_variables self @top_level end end rdoc/markdown.rb000064400001370135147635155430007671 0ustar00# coding: UTF-8 # :markup: markdown ## # RDoc::Markdown as described by the [markdown syntax][syntax]. # # To choose Markdown as your only default format see # RDoc::Options@Saved+Options for instructions on setting up a `.doc_options` # file to store your project default. # # ## Extensions # # The following markdown extensions are supported by the parser, but not all # are used in RDoc output by default. # # ### RDoc # # The RDoc Markdown parser has the following built-in behaviors that cannot be # disabled. # # Underscores embedded in words are never interpreted as emphasis. (While the # [markdown dingus][dingus] emphasizes in-word underscores, neither the # Markdown syntax nor MarkdownTest mention this behavior.) # # For HTML output, RDoc always auto-links bare URLs. # # ### Break on Newline # # The break_on_newline extension converts all newlines into hard line breaks # as in [Github Flavored Markdown][GFM]. This extension is disabled by # default. # # ### CSS # # The #css extension enables CSS blocks to be included in the output, but they # are not used for any built-in RDoc output format. This extension is disabled # by default. # # Example: # # # # ### Definition Lists # # The definition_lists extension allows definition lists using the [PHP # Markdown Extra syntax][PHPE], but only one label and definition are supported # at this time. This extension is enabled by default. # # Example: # # ``` # cat # : A small furry mammal # that seems to sleep a lot # # ant # : A little insect that is known # to enjoy picnics # # ``` # # Produces: # # cat # : A small furry mammal # that seems to sleep a lot # # ant # : A little insect that is known # to enjoy picnics # # ### Github # # The #github extension enables a partial set of [Github Flavored Markdown] # [GFM]. This extension is enabled by default. # # Supported github extensions include: # # #### Fenced code blocks # # Use ` ``` ` around a block of code instead of indenting it four spaces. # # #### Syntax highlighting # # Use ` ``` ruby ` as the start of a code fence to add syntax highlighting. # (Currently only `ruby` syntax is supported). # # ### HTML # # Enables raw HTML to be included in the output. This extension is enabled by # default. # # Example: # # # ... #
    # # ### Notes # # The #notes extension enables footnote support. This extension is enabled by # default. # # Example: # # Here is some text[^1] including an inline footnote ^[for short footnotes] # # ... # # [^1]: With the footnote text down at the bottom # # Produces: # # Here is some text[^1] including an inline footnote ^[for short footnotes] # # [^1]: With the footnote text down at the bottom # # ## Limitations # # * Link titles are not used # * Image links are not generated correctly # * Footnotes are collapsed into a single paragraph # # ## Author # # This markdown parser is a port to kpeg from [peg-markdown][pegmarkdown] by # John MacFarlane. # # It is used under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # The port to kpeg was performed by Eric Hodel and Evan Phoenix # # [dingus]: http://daringfireball.net/projects/markdown/dingus # [GFM]: http://github.github.com/github-flavored-markdown/ # [pegmarkdown]: https://github.com/jgm/peg-markdown # [PHPE]: http://michelf.com/projects/php-markdown/extra/#def-list # [syntax]: http://daringfireball.net/projects/markdown/syntax #-- # Last updated to jgm/peg-markdown commit 8f8fc22ef0 class RDoc::Markdown # :stopdoc: # This is distinct from setup_parser so that a standalone parser # can redefine #initialize and still have access to the proper # parser setup code. def initialize(str, debug=false) setup_parser(str, debug) end # Prepares for parsing +str+. If you define a custom initialize you must # call this method before #parse def setup_parser(str, debug=false) @string = str @pos = 0 @memoizations = Hash.new { |h,k| h[k] = {} } @result = nil @failed_rule = nil @failing_rule_offset = -1 setup_foreign_grammar end attr_reader :string attr_reader :failing_rule_offset attr_accessor :result, :pos def current_column(target=pos) if c = string.rindex("\n", target-1) return target - c - 1 end target + 1 end def current_line(target=pos) cur_offset = 0 cur_line = 0 string.each_line do |line| cur_line += 1 cur_offset += line.size return cur_line if cur_offset >= target end -1 end def lines lines = [] string.each_line { |l| lines << l } lines end def get_text(start) @string[start..@pos-1] end def show_pos width = 10 if @pos < width "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" else "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" end end def failure_info l = current_line @failing_rule_offset c = current_column @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" else "line #{l}, column #{c}: failed rule '#{@failed_rule}'" end end def failure_caret l = current_line @failing_rule_offset c = current_column @failing_rule_offset line = lines[l-1] "#{line}\n#{' ' * (c - 1)}^" end def failure_character l = current_line @failing_rule_offset c = current_column @failing_rule_offset lines[l-1][c-1, 1] end def failure_oneline l = current_line @failing_rule_offset c = current_column @failing_rule_offset char = lines[l-1][c-1, 1] if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" else "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" end end class ParseError < RuntimeError end def raise_error raise ParseError, failure_oneline end def show_error(io=STDOUT) error_pos = @failing_rule_offset line_no = current_line(error_pos) col_no = current_column(error_pos) io.puts "On line #{line_no}, column #{col_no}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" else io.puts "Failed to match rule '#{@failed_rule}'" end io.puts "Got: #{string[error_pos,1].inspect}" line = lines[line_no-1] io.puts "=> #{line}" io.print(" " * (col_no + 3)) io.puts "^" end def set_failed_rule(name) if @pos > @failing_rule_offset @failed_rule = name @failing_rule_offset = @pos end end attr_reader :failed_rule def match_string(str) len = str.size if @string[pos,len] == str @pos += len return str end return nil end def scan(reg) if m = reg.match(@string[@pos..-1]) width = m.end(0) @pos += width return true end return nil end if "".respond_to? :getbyte def get_byte if @pos >= @string.size return nil end s = @string.getbyte @pos @pos += 1 s end else def get_byte if @pos >= @string.size return nil end s = @string[@pos] @pos += 1 s end end def parse(rule=nil) # We invoke the rules indirectly via apply # instead of by just calling them as methods because # if the rules use left recursion, apply needs to # manage that. if !rule apply(:_root) else method = rule.gsub("-","_hyphen_") apply :"_#{method}" end end class MemoEntry def initialize(ans, pos) @ans = ans @pos = pos @result = nil @set = false @left_rec = false end attr_reader :ans, :pos, :result, :set attr_accessor :left_rec def move!(ans, pos, result) @ans = ans @pos = pos @result = result @set = true @left_rec = false end end def external_invoke(other, rule, *args) old_pos = @pos old_string = @string @pos = other.pos @string = other.string begin if val = __send__(rule, *args) other.pos = @pos other.result = @result else other.set_failed_rule "#{self.class}##{rule}" end val ensure @pos = old_pos @string = old_string end end def apply_with_args(rule, *args) memo_key = [rule, args] if m = @memoizations[memo_key][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[memo_key][@pos] = m start_pos = @pos ans = __send__ rule, *args lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, args, start_pos, m) else return ans end return ans end end def apply(rule) if m = @memoizations[rule][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[rule][@pos] = m start_pos = @pos ans = __send__ rule lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, nil, start_pos, m) else return ans end return ans end end def grow_lr(rule, args, start_pos, m) while true @pos = start_pos @result = m.result if args ans = __send__ rule, *args else ans = __send__ rule end return nil unless ans break if @pos <= m.pos m.move! ans, @pos, @result end @result = m.result @pos = m.pos return m.ans end class RuleInfo def initialize(name, rendered) @name = name @rendered = rendered end attr_reader :name, :rendered end def self.rule_info(name, rendered) RuleInfo.new(name, rendered) end # :startdoc: require 'rubygems' require 'rdoc' require 'rdoc/markup/to_joined_paragraph' require 'rdoc/markdown/entities' if RUBY_VERSION > '1.9' then require 'rdoc/markdown/literals_1_9' else require 'rdoc/markdown/literals_1_8' end ## # Supported extensions EXTENSIONS = [] ## # Extensions enabled by default DEFAULT_EXTENSIONS = [ :definition_lists, :github, :html, :notes, ] # :section: Extensions ## # Creates extension methods for the `name` extension to enable and disable # the extension and to query if they are active. def self.extension name EXTENSIONS << name eval <<-RUBY def #{name}? extension? __method__ end def #{name}= enable extension __method__, enable end RUBY end ## # Converts all newlines into hard breaks extension :break_on_newline ## # Allow style blocks extension :css ## # Allow PHP Markdown Extras style definition lists extension :definition_lists ## # Allow Github Flavored Markdown extension :github ## # Allow HTML extension :html ## # Enables the notes extension extension :notes # :section: ## # Parses the `markdown` document into an RDoc::Document using the default # extensions. def self.parse markdown parser = new parser.parse markdown end # TODO remove when kpeg 0.10 is released alias orig_initialize initialize # :nodoc: ## # Creates a new markdown parser that enables the given +extensions+. def initialize extensions = DEFAULT_EXTENSIONS, debug = false @debug = debug @formatter = RDoc::Markup::ToJoinedParagraph.new @extensions = extensions @references = nil @unlinked_references = nil @footnotes = nil @note_order = nil end ## # Wraps `text` in emphasis for rdoc inline formatting def emphasis text if text =~ /\A[a-z\d.\/]+\z/i then "_#{text}_" else "#{text}" end end ## # :category: Extensions # # Is the extension `name` enabled? def extension? name name = name.to_s.delete('?').intern @extensions.include? name end ## # :category: Extensions # # Enables or disables the extension with `name` def extension name, enable name = name.to_s.delete('=').intern if enable then @extensions |= [name] else @extensions -= [name] end end ## # Parses `text` in a clone of this parser. This is used for handling nested # lists the same way as markdown_parser. def inner_parse text # :nodoc: parser = clone parser.setup_parser text, @debug parser.peg_parse doc = parser.result doc.accept @formatter doc.parts end ## # Finds a link reference for `label` and creates a new link to it with # `content` as the link text. If `label` was not encountered in the # reference-gathering parser pass the label and content are reconstructed # with the linking `text` (usually whitespace). def link_to content, label = content, text = nil raise 'enable notes extension' if content.start_with? '^' and label.equal? content if ref = @references[label] then "{#{content}}[#{ref}]" elsif label.equal? content then "[#{content}]#{text}" else "[#{content}]#{text}[#{label}]" end end ## # Creates an RDoc::Markup::ListItem by parsing the `unparsed` content from # the first parsing pass. def list_item_from unparsed parsed = inner_parse unparsed.join RDoc::Markup::ListItem.new nil, *parsed end ## # Stores `label` as a note and fills in previously unknown note references. def note label #foottext = "rdoc-label:foottext-#{label}:footmark-#{label}" #ref.replace foottext if ref = @unlinked_notes.delete(label) @notes[label] = foottext #"{^1}[rdoc-label:footmark-#{label}:foottext-#{label}] " end ## # Creates a new link for the footnote `reference` and adds the reference to # the note order list for proper display at the end of the document. def note_for ref @note_order << ref label = @note_order.length "{*#{label}}[rdoc-label:foottext-#{label}:footmark-#{label}]" end ## # The internal kpeg parse method alias peg_parse parse # :nodoc: ## # Creates an RDoc::Markup::Paragraph from `parts` and including # extension-specific behavior def paragraph parts parts = parts.map do |part| if "\n" == part then RDoc::Markup::HardBreak.new else part end end if break_on_newline? RDoc::Markup::Paragraph.new(*parts) end ## # Parses `markdown` into an RDoc::Document def parse markdown @references = {} @unlinked_references = {} markdown += "\n\n" setup_parser markdown, @debug peg_parse 'References' if notes? then @footnotes = {} setup_parser markdown, @debug peg_parse 'Notes' # using note_order on the first pass would be a bug @note_order = [] end setup_parser markdown, @debug peg_parse doc = result if notes? and not @footnotes.empty? then doc << RDoc::Markup::Rule.new(1) @note_order.each_with_index do |ref, index| label = index + 1 note = @footnotes[ref] link = "{^#{label}}[rdoc-label:footmark-#{label}:foottext-#{label}] " note.parts.unshift link doc << note end end doc.accept @formatter doc end ## # Stores `label` as a reference to `link` and fills in previously unknown # link references. def reference label, link if ref = @unlinked_references.delete(label) then ref.replace link end @references[label] = link end ## # Wraps `text` in strong markup for rdoc inline formatting def strong text if text =~ /\A[a-z\d.\/-]+\z/i then "*#{text}*" else "#{text}" end end # :stopdoc: def setup_foreign_grammar @_grammar_literals = RDoc::Markdown::Literals.new(nil) end # root = Doc def _root _tmp = apply(:_Doc) set_failed_rule :_root unless _tmp return _tmp end # Doc = BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) } def _Doc _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_BOM) unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _ary = [] while true _tmp = apply(:_Block) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Document.new(*a.compact) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Doc unless _tmp return _tmp end # Block = BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain) def _Block _save = self.pos while true # sequence while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save2 = self.pos while true # choice _tmp = apply(:_BlockQuote) break if _tmp self.pos = _save2 _tmp = apply(:_Verbatim) break if _tmp self.pos = _save2 _tmp = apply(:_CodeFence) break if _tmp self.pos = _save2 _tmp = apply(:_Note) break if _tmp self.pos = _save2 _tmp = apply(:_Reference) break if _tmp self.pos = _save2 _tmp = apply(:_HorizontalRule) break if _tmp self.pos = _save2 _tmp = apply(:_Heading) break if _tmp self.pos = _save2 _tmp = apply(:_OrderedList) break if _tmp self.pos = _save2 _tmp = apply(:_BulletList) break if _tmp self.pos = _save2 _tmp = apply(:_DefinitionList) break if _tmp self.pos = _save2 _tmp = apply(:_HtmlBlock) break if _tmp self.pos = _save2 _tmp = apply(:_StyleBlock) break if _tmp self.pos = _save2 _tmp = apply(:_Para) break if _tmp self.pos = _save2 _tmp = apply(:_Plain) break if _tmp self.pos = _save2 break end # end choice unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Block unless _tmp return _tmp end # Para = NonindentSpace Inlines:a BlankLine+ { paragraph a } def _Para _save = self.pos while true # sequence _tmp = apply(:_NonindentSpace) unless _tmp self.pos = _save break end _tmp = apply(:_Inlines) a = @result unless _tmp self.pos = _save break end _save1 = self.pos _tmp = apply(:_BlankLine) if _tmp while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; paragraph a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Para unless _tmp return _tmp end # Plain = Inlines:a { paragraph a } def _Plain _save = self.pos while true # sequence _tmp = apply(:_Inlines) a = @result unless _tmp self.pos = _save break end @result = begin; paragraph a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Plain unless _tmp return _tmp end # AtxInline = !Newline !(Sp? "#"* Sp Newline) Inline def _AtxInline _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_Sp) unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save3 break end while true _tmp = match_string("#") break unless _tmp end _tmp = true unless _tmp self.pos = _save3 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save3 break end _tmp = apply(:_Newline) unless _tmp self.pos = _save3 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AtxInline unless _tmp return _tmp end # AtxStart = < ("######" | "#####" | "####" | "###" | "##" | "#") > { text.length } def _AtxStart _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos while true # choice _tmp = match_string("######") break if _tmp self.pos = _save1 _tmp = match_string("#####") break if _tmp self.pos = _save1 _tmp = match_string("####") break if _tmp self.pos = _save1 _tmp = match_string("###") break if _tmp self.pos = _save1 _tmp = match_string("##") break if _tmp self.pos = _save1 _tmp = match_string("#") break if _tmp self.pos = _save1 break end # end choice if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text.length ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AtxStart unless _tmp return _tmp end # AtxHeading = AtxStart:s Sp? AtxInline+:a (Sp? "#"* Sp)? Newline { RDoc::Markup::Heading.new(s, a.join) } def _AtxHeading _save = self.pos while true # sequence _tmp = apply(:_AtxStart) s = @result unless _tmp self.pos = _save break end _save1 = self.pos _tmp = apply(:_Sp) unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_AtxInline) if _tmp _ary << @result while true _tmp = apply(:_AtxInline) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end a = @result unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = apply(:_Sp) unless _tmp _tmp = true self.pos = _save5 end unless _tmp self.pos = _save4 break end while true _tmp = match_string("#") break unless _tmp end _tmp = true unless _tmp self.pos = _save4 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save4 end break end # end sequence unless _tmp _tmp = true self.pos = _save3 end unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Heading.new(s, a.join) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AtxHeading unless _tmp return _tmp end # SetextHeading = (SetextHeading1 | SetextHeading2) def _SetextHeading _save = self.pos while true # choice _tmp = apply(:_SetextHeading1) break if _tmp self.pos = _save _tmp = apply(:_SetextHeading2) break if _tmp self.pos = _save break end # end choice set_failed_rule :_SetextHeading unless _tmp return _tmp end # SetextBottom1 = "===" "="* Newline def _SetextBottom1 _save = self.pos while true # sequence _tmp = match_string("===") unless _tmp self.pos = _save break end while true _tmp = match_string("=") break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextBottom1 unless _tmp return _tmp end # SetextBottom2 = "---" "-"* Newline def _SetextBottom2 _save = self.pos while true # sequence _tmp = match_string("---") unless _tmp self.pos = _save break end while true _tmp = match_string("-") break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextBottom2 unless _tmp return _tmp end # SetextHeading1 = &(RawLine SetextBottom1) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom1 { RDoc::Markup::Heading.new(1, a.join) } def _SetextHeading1 _save = self.pos while true # sequence _save1 = self.pos _save2 = self.pos while true # sequence _tmp = apply(:_RawLine) unless _tmp self.pos = _save2 break end _tmp = apply(:_SetextBottom1) unless _tmp self.pos = _save2 end break end # end sequence self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = apply(:_Endline) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save4 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save6 = self.pos while true # sequence _save7 = self.pos _tmp = apply(:_Endline) _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save6 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save6 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end unless _tmp self.pos = _save break end _save8 = self.pos _tmp = apply(:_Sp) unless _tmp _tmp = true self.pos = _save8 end unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end _tmp = apply(:_SetextBottom1) unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Heading.new(1, a.join) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextHeading1 unless _tmp return _tmp end # SetextHeading2 = &(RawLine SetextBottom2) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) } def _SetextHeading2 _save = self.pos while true # sequence _save1 = self.pos _save2 = self.pos while true # sequence _tmp = apply(:_RawLine) unless _tmp self.pos = _save2 break end _tmp = apply(:_SetextBottom2) unless _tmp self.pos = _save2 end break end # end sequence self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = apply(:_Endline) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save4 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save6 = self.pos while true # sequence _save7 = self.pos _tmp = apply(:_Endline) _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _tmp = apply(:_Inline) b = @result unless _tmp self.pos = _save6 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save6 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end unless _tmp self.pos = _save break end _save8 = self.pos _tmp = apply(:_Sp) unless _tmp _tmp = true self.pos = _save8 end unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end _tmp = apply(:_SetextBottom2) unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Heading.new(2, a.join) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_SetextHeading2 unless _tmp return _tmp end # Heading = (SetextHeading | AtxHeading) def _Heading _save = self.pos while true # choice _tmp = apply(:_SetextHeading) break if _tmp self.pos = _save _tmp = apply(:_AtxHeading) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Heading unless _tmp return _tmp end # BlockQuote = BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) } def _BlockQuote _save = self.pos while true # sequence _tmp = apply(:_BlockQuoteRaw) a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::BlockQuote.new(*a) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BlockQuote unless _tmp return _tmp end # BlockQuoteRaw = StartList:a (">" " "? Line:l { a << l } (!">" !BlankLine Line:c { a << c })* (BlankLine:n { a << n })*)+ { inner_parse a.join } def _BlockQuoteRaw _save = self.pos while true # sequence _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _tmp = match_string(">") unless _tmp self.pos = _save2 break end _save3 = self.pos _tmp = match_string(" ") unless _tmp _tmp = true self.pos = _save3 end unless _tmp self.pos = _save2 break end _tmp = apply(:_Line) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 break end while true _save5 = self.pos while true # sequence _save6 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save5 break end _tmp = apply(:_Line) c = @result unless _tmp self.pos = _save5 break end @result = begin; a << c ; end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 break end while true _save9 = self.pos while true # sequence _tmp = apply(:_BlankLine) n = @result unless _tmp self.pos = _save9 break end @result = begin; a << n ; end _tmp = true unless _tmp self.pos = _save9 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save10 = self.pos while true # sequence _tmp = match_string(">") unless _tmp self.pos = _save10 break end _save11 = self.pos _tmp = match_string(" ") unless _tmp _tmp = true self.pos = _save11 end unless _tmp self.pos = _save10 break end _tmp = apply(:_Line) l = @result unless _tmp self.pos = _save10 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save10 break end while true _save13 = self.pos while true # sequence _save14 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save14 unless _tmp self.pos = _save13 break end _save15 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save15 unless _tmp self.pos = _save13 break end _tmp = apply(:_Line) c = @result unless _tmp self.pos = _save13 break end @result = begin; a << c ; end _tmp = true unless _tmp self.pos = _save13 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save10 break end while true _save17 = self.pos while true # sequence _tmp = apply(:_BlankLine) n = @result unless _tmp self.pos = _save17 break end @result = begin; a << n ; end _tmp = true unless _tmp self.pos = _save17 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save10 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; inner_parse a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BlockQuoteRaw unless _tmp return _tmp end # NonblankIndentedLine = !BlankLine IndentedLine def _NonblankIndentedLine _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_IndentedLine) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_NonblankIndentedLine unless _tmp return _tmp end # VerbatimChunk = BlankLine*:a NonblankIndentedLine+:b { a.concat b } def _VerbatimChunk _save = self.pos while true # sequence _ary = [] while true _tmp = apply(:_BlankLine) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary a = @result unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_NonblankIndentedLine) if _tmp _ary << @result while true _tmp = apply(:_NonblankIndentedLine) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end b = @result unless _tmp self.pos = _save break end @result = begin; a.concat b ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_VerbatimChunk unless _tmp return _tmp end # Verbatim = VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) } def _Verbatim _save = self.pos while true # sequence _save1 = self.pos _ary = [] _tmp = apply(:_VerbatimChunk) if _tmp _ary << @result while true _tmp = apply(:_VerbatimChunk) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Verbatim.new(*a.flatten) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Verbatim unless _tmp return _tmp end # HorizontalRule = NonindentSpace ("*" Sp "*" Sp "*" (Sp "*")* | "-" Sp "-" Sp "-" (Sp "-")* | "_" Sp "_" Sp "_" (Sp "_")*) Sp Newline BlankLine+ { RDoc::Markup::Rule.new 1 } def _HorizontalRule _save = self.pos while true # sequence _tmp = apply(:_NonindentSpace) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _tmp = match_string("*") unless _tmp self.pos = _save2 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save2 break end _tmp = match_string("*") unless _tmp self.pos = _save2 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save2 break end _tmp = match_string("*") unless _tmp self.pos = _save2 break end while true _save4 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save4 break end _tmp = match_string("*") unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _save5 = self.pos while true # sequence _tmp = match_string("-") unless _tmp self.pos = _save5 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save5 break end _tmp = match_string("-") unless _tmp self.pos = _save5 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save5 break end _tmp = match_string("-") unless _tmp self.pos = _save5 break end while true _save7 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save7 break end _tmp = match_string("-") unless _tmp self.pos = _save7 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save1 _save8 = self.pos while true # sequence _tmp = match_string("_") unless _tmp self.pos = _save8 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save8 break end _tmp = match_string("_") unless _tmp self.pos = _save8 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save8 break end _tmp = match_string("_") unless _tmp self.pos = _save8 break end while true _save10 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save10 break end _tmp = match_string("_") unless _tmp self.pos = _save10 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save8 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end _save11 = self.pos _tmp = apply(:_BlankLine) if _tmp while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true else self.pos = _save11 end unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::Rule.new 1 ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HorizontalRule unless _tmp return _tmp end # Bullet = !HorizontalRule NonindentSpace ("+" | "*" | "-") Spacechar+ def _Bullet _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_HorizontalRule) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_NonindentSpace) unless _tmp self.pos = _save break end _save2 = self.pos while true # choice _tmp = match_string("+") break if _tmp self.pos = _save2 _tmp = match_string("*") break if _tmp self.pos = _save2 _tmp = match_string("-") break if _tmp self.pos = _save2 break end # end choice unless _tmp self.pos = _save break end _save3 = self.pos _tmp = apply(:_Spacechar) if _tmp while true _tmp = apply(:_Spacechar) break unless _tmp end _tmp = true else self.pos = _save3 end unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Bullet unless _tmp return _tmp end # BulletList = &Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) } def _BulletList _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Bullet) self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos while true # choice _tmp = apply(:_ListTight) break if _tmp self.pos = _save2 _tmp = apply(:_ListLoose) break if _tmp self.pos = _save2 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::List.new(:BULLET, *a) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BulletList unless _tmp return _tmp end # ListTight = ListItemTight+:a BlankLine* !(Bullet | Enumerator) { a } def _ListTight _save = self.pos while true # sequence _save1 = self.pos _ary = [] _tmp = apply(:_ListItemTight) if _tmp _ary << @result while true _tmp = apply(:_ListItemTight) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end a = @result unless _tmp self.pos = _save break end while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save3 = self.pos _save4 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save4 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListTight unless _tmp return _tmp end # ListLoose = StartList:a (ListItem:b BlankLine* { a << b })+ { a } def _ListLoose _save = self.pos while true # sequence _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _tmp = apply(:_ListItem) b = @result unless _tmp self.pos = _save2 break end while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true unless _tmp self.pos = _save2 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save4 = self.pos while true # sequence _tmp = apply(:_ListItem) b = @result unless _tmp self.pos = _save4 break end while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true unless _tmp self.pos = _save4 break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListLoose unless _tmp return _tmp end # ListItem = (Bullet | Enumerator) StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a } def _ListItem _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save1 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _tmp = apply(:_ListBlock) b = @result unless _tmp self.pos = _save break end @result = begin; a << b ; end _tmp = true unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _tmp = apply(:_ListContinuationBlock) c = @result unless _tmp self.pos = _save3 break end @result = begin; a.push(*c) ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; list_item_from a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListItem unless _tmp return _tmp end # ListItemTight = (Bullet | Enumerator) ListBlock:a (!BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a } def _ListItemTight _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save1 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_ListBlock) a = @result unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_ListContinuationBlock) b = @result unless _tmp self.pos = _save3 break end @result = begin; a.push(*b) ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save5 = self.pos _tmp = apply(:_ListContinuationBlock) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save break end @result = begin; list_item_from a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListItemTight unless _tmp return _tmp end # ListBlock = !BlankLine Line:a ListBlockLine*:c { [a, *c] } def _ListBlock _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Line) a = @result unless _tmp self.pos = _save break end _ary = [] while true _tmp = apply(:_ListBlockLine) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary c = @result unless _tmp self.pos = _save break end @result = begin; [a, *c] ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListBlock unless _tmp return _tmp end # ListContinuationBlock = StartList:a BlankLine* { a << "\n" } (Indent ListBlock:b { a.concat b })+ { a } def _ListContinuationBlock _save = self.pos while true # sequence _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; a << "\n" ; end _tmp = true unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _tmp = apply(:_Indent) unless _tmp self.pos = _save3 break end _tmp = apply(:_ListBlock) b = @result unless _tmp self.pos = _save3 break end @result = begin; a.concat b ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save4 = self.pos while true # sequence _tmp = apply(:_Indent) unless _tmp self.pos = _save4 break end _tmp = apply(:_ListBlock) b = @result unless _tmp self.pos = _save4 break end @result = begin; a.concat b ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListContinuationBlock unless _tmp return _tmp end # Enumerator = NonindentSpace [0-9]+ "." Spacechar+ def _Enumerator _save = self.pos while true # sequence _tmp = apply(:_NonindentSpace) unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos _tmp = get_byte if _tmp unless _tmp >= 48 and _tmp <= 57 self.pos = _save2 _tmp = nil end end if _tmp while true _save3 = self.pos _tmp = get_byte if _tmp unless _tmp >= 48 and _tmp <= 57 self.pos = _save3 _tmp = nil end end break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end _tmp = match_string(".") unless _tmp self.pos = _save break end _save4 = self.pos _tmp = apply(:_Spacechar) if _tmp while true _tmp = apply(:_Spacechar) break unless _tmp end _tmp = true else self.pos = _save4 end unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Enumerator unless _tmp return _tmp end # OrderedList = &Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) } def _OrderedList _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Enumerator) self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos while true # choice _tmp = apply(:_ListTight) break if _tmp self.pos = _save2 _tmp = apply(:_ListLoose) break if _tmp self.pos = _save2 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::List.new(:NUMBER, *a) ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OrderedList unless _tmp return _tmp end # ListBlockLine = !BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine def _ListBlockLine _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_Indent) unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save3 break end _save5 = self.pos while true # choice _tmp = apply(:_Bullet) break if _tmp self.pos = _save5 _tmp = apply(:_Enumerator) break if _tmp self.pos = _save5 break end # end choice unless _tmp self.pos = _save3 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save6 = self.pos _tmp = apply(:_HorizontalRule) _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save break end _tmp = apply(:_OptionallyIndentedLine) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ListBlockLine unless _tmp return _tmp end # HtmlBlockOpenAddress = "<" Spnl ("address" | "ADDRESS") Spnl HtmlAttribute* ">" def _HtmlBlockOpenAddress _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("address") break if _tmp self.pos = _save1 _tmp = match_string("ADDRESS") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenAddress unless _tmp return _tmp end # HtmlBlockCloseAddress = "<" Spnl "/" ("address" | "ADDRESS") Spnl ">" def _HtmlBlockCloseAddress _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("address") break if _tmp self.pos = _save1 _tmp = match_string("ADDRESS") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseAddress unless _tmp return _tmp end # HtmlBlockAddress = HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress def _HtmlBlockAddress _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenAddress) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockAddress) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseAddress) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseAddress) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockAddress unless _tmp return _tmp end # HtmlBlockOpenBlockquote = "<" Spnl ("blockquote" | "BLOCKQUOTE") Spnl HtmlAttribute* ">" def _HtmlBlockOpenBlockquote _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("blockquote") break if _tmp self.pos = _save1 _tmp = match_string("BLOCKQUOTE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenBlockquote unless _tmp return _tmp end # HtmlBlockCloseBlockquote = "<" Spnl "/" ("blockquote" | "BLOCKQUOTE") Spnl ">" def _HtmlBlockCloseBlockquote _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("blockquote") break if _tmp self.pos = _save1 _tmp = match_string("BLOCKQUOTE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseBlockquote unless _tmp return _tmp end # HtmlBlockBlockquote = HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote def _HtmlBlockBlockquote _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenBlockquote) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockBlockquote) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseBlockquote) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseBlockquote) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockBlockquote unless _tmp return _tmp end # HtmlBlockOpenCenter = "<" Spnl ("center" | "CENTER") Spnl HtmlAttribute* ">" def _HtmlBlockOpenCenter _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("center") break if _tmp self.pos = _save1 _tmp = match_string("CENTER") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenCenter unless _tmp return _tmp end # HtmlBlockCloseCenter = "<" Spnl "/" ("center" | "CENTER") Spnl ">" def _HtmlBlockCloseCenter _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("center") break if _tmp self.pos = _save1 _tmp = match_string("CENTER") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseCenter unless _tmp return _tmp end # HtmlBlockCenter = HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter def _HtmlBlockCenter _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenCenter) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockCenter) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseCenter) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseCenter) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCenter unless _tmp return _tmp end # HtmlBlockOpenDir = "<" Spnl ("dir" | "DIR") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDir _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dir") break if _tmp self.pos = _save1 _tmp = match_string("DIR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDir unless _tmp return _tmp end # HtmlBlockCloseDir = "<" Spnl "/" ("dir" | "DIR") Spnl ">" def _HtmlBlockCloseDir _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dir") break if _tmp self.pos = _save1 _tmp = match_string("DIR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDir unless _tmp return _tmp end # HtmlBlockDir = HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir def _HtmlBlockDir _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDir) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDir) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDir) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDir) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDir unless _tmp return _tmp end # HtmlBlockOpenDiv = "<" Spnl ("div" | "DIV") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDiv _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("div") break if _tmp self.pos = _save1 _tmp = match_string("DIV") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDiv unless _tmp return _tmp end # HtmlBlockCloseDiv = "<" Spnl "/" ("div" | "DIV") Spnl ">" def _HtmlBlockCloseDiv _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("div") break if _tmp self.pos = _save1 _tmp = match_string("DIV") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDiv unless _tmp return _tmp end # HtmlBlockDiv = HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv def _HtmlBlockDiv _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDiv) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDiv) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDiv) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDiv) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDiv unless _tmp return _tmp end # HtmlBlockOpenDl = "<" Spnl ("dl" | "DL") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dl") break if _tmp self.pos = _save1 _tmp = match_string("DL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDl unless _tmp return _tmp end # HtmlBlockCloseDl = "<" Spnl "/" ("dl" | "DL") Spnl ">" def _HtmlBlockCloseDl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dl") break if _tmp self.pos = _save1 _tmp = match_string("DL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDl unless _tmp return _tmp end # HtmlBlockDl = HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl def _HtmlBlockDl _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDl) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDl) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDl) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDl unless _tmp return _tmp end # HtmlBlockOpenFieldset = "<" Spnl ("fieldset" | "FIELDSET") Spnl HtmlAttribute* ">" def _HtmlBlockOpenFieldset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("fieldset") break if _tmp self.pos = _save1 _tmp = match_string("FIELDSET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenFieldset unless _tmp return _tmp end # HtmlBlockCloseFieldset = "<" Spnl "/" ("fieldset" | "FIELDSET") Spnl ">" def _HtmlBlockCloseFieldset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("fieldset") break if _tmp self.pos = _save1 _tmp = match_string("FIELDSET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseFieldset unless _tmp return _tmp end # HtmlBlockFieldset = HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset def _HtmlBlockFieldset _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenFieldset) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockFieldset) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseFieldset) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseFieldset) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockFieldset unless _tmp return _tmp end # HtmlBlockOpenForm = "<" Spnl ("form" | "FORM") Spnl HtmlAttribute* ">" def _HtmlBlockOpenForm _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("form") break if _tmp self.pos = _save1 _tmp = match_string("FORM") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenForm unless _tmp return _tmp end # HtmlBlockCloseForm = "<" Spnl "/" ("form" | "FORM") Spnl ">" def _HtmlBlockCloseForm _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("form") break if _tmp self.pos = _save1 _tmp = match_string("FORM") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseForm unless _tmp return _tmp end # HtmlBlockForm = HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm def _HtmlBlockForm _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenForm) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockForm) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseForm) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseForm) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockForm unless _tmp return _tmp end # HtmlBlockOpenH1 = "<" Spnl ("h1" | "H1") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH1 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h1") break if _tmp self.pos = _save1 _tmp = match_string("H1") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH1 unless _tmp return _tmp end # HtmlBlockCloseH1 = "<" Spnl "/" ("h1" | "H1") Spnl ">" def _HtmlBlockCloseH1 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h1") break if _tmp self.pos = _save1 _tmp = match_string("H1") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH1 unless _tmp return _tmp end # HtmlBlockH1 = HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1 def _HtmlBlockH1 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH1) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH1) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH1) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH1) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH1 unless _tmp return _tmp end # HtmlBlockOpenH2 = "<" Spnl ("h2" | "H2") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH2 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h2") break if _tmp self.pos = _save1 _tmp = match_string("H2") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH2 unless _tmp return _tmp end # HtmlBlockCloseH2 = "<" Spnl "/" ("h2" | "H2") Spnl ">" def _HtmlBlockCloseH2 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h2") break if _tmp self.pos = _save1 _tmp = match_string("H2") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH2 unless _tmp return _tmp end # HtmlBlockH2 = HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2 def _HtmlBlockH2 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH2) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH2) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH2) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH2) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH2 unless _tmp return _tmp end # HtmlBlockOpenH3 = "<" Spnl ("h3" | "H3") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH3 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h3") break if _tmp self.pos = _save1 _tmp = match_string("H3") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH3 unless _tmp return _tmp end # HtmlBlockCloseH3 = "<" Spnl "/" ("h3" | "H3") Spnl ">" def _HtmlBlockCloseH3 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h3") break if _tmp self.pos = _save1 _tmp = match_string("H3") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH3 unless _tmp return _tmp end # HtmlBlockH3 = HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3 def _HtmlBlockH3 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH3) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH3) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH3) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH3) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH3 unless _tmp return _tmp end # HtmlBlockOpenH4 = "<" Spnl ("h4" | "H4") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH4 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h4") break if _tmp self.pos = _save1 _tmp = match_string("H4") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH4 unless _tmp return _tmp end # HtmlBlockCloseH4 = "<" Spnl "/" ("h4" | "H4") Spnl ">" def _HtmlBlockCloseH4 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h4") break if _tmp self.pos = _save1 _tmp = match_string("H4") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH4 unless _tmp return _tmp end # HtmlBlockH4 = HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4 def _HtmlBlockH4 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH4) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH4) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH4) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH4) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH4 unless _tmp return _tmp end # HtmlBlockOpenH5 = "<" Spnl ("h5" | "H5") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH5 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h5") break if _tmp self.pos = _save1 _tmp = match_string("H5") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH5 unless _tmp return _tmp end # HtmlBlockCloseH5 = "<" Spnl "/" ("h5" | "H5") Spnl ">" def _HtmlBlockCloseH5 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h5") break if _tmp self.pos = _save1 _tmp = match_string("H5") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH5 unless _tmp return _tmp end # HtmlBlockH5 = HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5 def _HtmlBlockH5 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH5) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH5) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH5) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH5) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH5 unless _tmp return _tmp end # HtmlBlockOpenH6 = "<" Spnl ("h6" | "H6") Spnl HtmlAttribute* ">" def _HtmlBlockOpenH6 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h6") break if _tmp self.pos = _save1 _tmp = match_string("H6") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenH6 unless _tmp return _tmp end # HtmlBlockCloseH6 = "<" Spnl "/" ("h6" | "H6") Spnl ">" def _HtmlBlockCloseH6 _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("h6") break if _tmp self.pos = _save1 _tmp = match_string("H6") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseH6 unless _tmp return _tmp end # HtmlBlockH6 = HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6 def _HtmlBlockH6 _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenH6) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockH6) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseH6) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseH6) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockH6 unless _tmp return _tmp end # HtmlBlockOpenMenu = "<" Spnl ("menu" | "MENU") Spnl HtmlAttribute* ">" def _HtmlBlockOpenMenu _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("menu") break if _tmp self.pos = _save1 _tmp = match_string("MENU") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenMenu unless _tmp return _tmp end # HtmlBlockCloseMenu = "<" Spnl "/" ("menu" | "MENU") Spnl ">" def _HtmlBlockCloseMenu _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("menu") break if _tmp self.pos = _save1 _tmp = match_string("MENU") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseMenu unless _tmp return _tmp end # HtmlBlockMenu = HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu def _HtmlBlockMenu _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenMenu) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockMenu) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseMenu) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseMenu) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockMenu unless _tmp return _tmp end # HtmlBlockOpenNoframes = "<" Spnl ("noframes" | "NOFRAMES") Spnl HtmlAttribute* ">" def _HtmlBlockOpenNoframes _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noframes") break if _tmp self.pos = _save1 _tmp = match_string("NOFRAMES") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenNoframes unless _tmp return _tmp end # HtmlBlockCloseNoframes = "<" Spnl "/" ("noframes" | "NOFRAMES") Spnl ">" def _HtmlBlockCloseNoframes _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noframes") break if _tmp self.pos = _save1 _tmp = match_string("NOFRAMES") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseNoframes unless _tmp return _tmp end # HtmlBlockNoframes = HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes def _HtmlBlockNoframes _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenNoframes) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockNoframes) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseNoframes) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseNoframes) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockNoframes unless _tmp return _tmp end # HtmlBlockOpenNoscript = "<" Spnl ("noscript" | "NOSCRIPT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenNoscript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noscript") break if _tmp self.pos = _save1 _tmp = match_string("NOSCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenNoscript unless _tmp return _tmp end # HtmlBlockCloseNoscript = "<" Spnl "/" ("noscript" | "NOSCRIPT") Spnl ">" def _HtmlBlockCloseNoscript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("noscript") break if _tmp self.pos = _save1 _tmp = match_string("NOSCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseNoscript unless _tmp return _tmp end # HtmlBlockNoscript = HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript def _HtmlBlockNoscript _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenNoscript) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockNoscript) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseNoscript) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseNoscript) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockNoscript unless _tmp return _tmp end # HtmlBlockOpenOl = "<" Spnl ("ol" | "OL") Spnl HtmlAttribute* ">" def _HtmlBlockOpenOl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ol") break if _tmp self.pos = _save1 _tmp = match_string("OL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenOl unless _tmp return _tmp end # HtmlBlockCloseOl = "<" Spnl "/" ("ol" | "OL") Spnl ">" def _HtmlBlockCloseOl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ol") break if _tmp self.pos = _save1 _tmp = match_string("OL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseOl unless _tmp return _tmp end # HtmlBlockOl = HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl def _HtmlBlockOl _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenOl) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockOl) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseOl) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseOl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOl unless _tmp return _tmp end # HtmlBlockOpenP = "<" Spnl ("p" | "P") Spnl HtmlAttribute* ">" def _HtmlBlockOpenP _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("p") break if _tmp self.pos = _save1 _tmp = match_string("P") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenP unless _tmp return _tmp end # HtmlBlockCloseP = "<" Spnl "/" ("p" | "P") Spnl ">" def _HtmlBlockCloseP _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("p") break if _tmp self.pos = _save1 _tmp = match_string("P") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseP unless _tmp return _tmp end # HtmlBlockP = HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP def _HtmlBlockP _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenP) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockP) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseP) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseP) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockP unless _tmp return _tmp end # HtmlBlockOpenPre = "<" Spnl ("pre" | "PRE") Spnl HtmlAttribute* ">" def _HtmlBlockOpenPre _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("pre") break if _tmp self.pos = _save1 _tmp = match_string("PRE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenPre unless _tmp return _tmp end # HtmlBlockClosePre = "<" Spnl "/" ("pre" | "PRE") Spnl ">" def _HtmlBlockClosePre _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("pre") break if _tmp self.pos = _save1 _tmp = match_string("PRE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockClosePre unless _tmp return _tmp end # HtmlBlockPre = HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre def _HtmlBlockPre _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenPre) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockPre) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockClosePre) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockClosePre) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockPre unless _tmp return _tmp end # HtmlBlockOpenTable = "<" Spnl ("table" | "TABLE") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTable _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("table") break if _tmp self.pos = _save1 _tmp = match_string("TABLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTable unless _tmp return _tmp end # HtmlBlockCloseTable = "<" Spnl "/" ("table" | "TABLE") Spnl ">" def _HtmlBlockCloseTable _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("table") break if _tmp self.pos = _save1 _tmp = match_string("TABLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTable unless _tmp return _tmp end # HtmlBlockTable = HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable def _HtmlBlockTable _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTable) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTable) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTable) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTable) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTable unless _tmp return _tmp end # HtmlBlockOpenUl = "<" Spnl ("ul" | "UL") Spnl HtmlAttribute* ">" def _HtmlBlockOpenUl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ul") break if _tmp self.pos = _save1 _tmp = match_string("UL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenUl unless _tmp return _tmp end # HtmlBlockCloseUl = "<" Spnl "/" ("ul" | "UL") Spnl ">" def _HtmlBlockCloseUl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("ul") break if _tmp self.pos = _save1 _tmp = match_string("UL") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseUl unless _tmp return _tmp end # HtmlBlockUl = HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl def _HtmlBlockUl _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenUl) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockUl) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseUl) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseUl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockUl unless _tmp return _tmp end # HtmlBlockOpenDd = "<" Spnl ("dd" | "DD") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dd") break if _tmp self.pos = _save1 _tmp = match_string("DD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDd unless _tmp return _tmp end # HtmlBlockCloseDd = "<" Spnl "/" ("dd" | "DD") Spnl ">" def _HtmlBlockCloseDd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dd") break if _tmp self.pos = _save1 _tmp = match_string("DD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDd unless _tmp return _tmp end # HtmlBlockDd = HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd def _HtmlBlockDd _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDd) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDd) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDd) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDd) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDd unless _tmp return _tmp end # HtmlBlockOpenDt = "<" Spnl ("dt" | "DT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenDt _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dt") break if _tmp self.pos = _save1 _tmp = match_string("DT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenDt unless _tmp return _tmp end # HtmlBlockCloseDt = "<" Spnl "/" ("dt" | "DT") Spnl ">" def _HtmlBlockCloseDt _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("dt") break if _tmp self.pos = _save1 _tmp = match_string("DT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseDt unless _tmp return _tmp end # HtmlBlockDt = HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt def _HtmlBlockDt _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenDt) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockDt) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseDt) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseDt) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockDt unless _tmp return _tmp end # HtmlBlockOpenFrameset = "<" Spnl ("frameset" | "FRAMESET") Spnl HtmlAttribute* ">" def _HtmlBlockOpenFrameset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("frameset") break if _tmp self.pos = _save1 _tmp = match_string("FRAMESET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenFrameset unless _tmp return _tmp end # HtmlBlockCloseFrameset = "<" Spnl "/" ("frameset" | "FRAMESET") Spnl ">" def _HtmlBlockCloseFrameset _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("frameset") break if _tmp self.pos = _save1 _tmp = match_string("FRAMESET") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseFrameset unless _tmp return _tmp end # HtmlBlockFrameset = HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset def _HtmlBlockFrameset _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenFrameset) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockFrameset) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseFrameset) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseFrameset) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockFrameset unless _tmp return _tmp end # HtmlBlockOpenLi = "<" Spnl ("li" | "LI") Spnl HtmlAttribute* ">" def _HtmlBlockOpenLi _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("li") break if _tmp self.pos = _save1 _tmp = match_string("LI") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenLi unless _tmp return _tmp end # HtmlBlockCloseLi = "<" Spnl "/" ("li" | "LI") Spnl ">" def _HtmlBlockCloseLi _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("li") break if _tmp self.pos = _save1 _tmp = match_string("LI") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseLi unless _tmp return _tmp end # HtmlBlockLi = HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi def _HtmlBlockLi _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenLi) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockLi) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseLi) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseLi) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockLi unless _tmp return _tmp end # HtmlBlockOpenTbody = "<" Spnl ("tbody" | "TBODY") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTbody _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tbody") break if _tmp self.pos = _save1 _tmp = match_string("TBODY") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTbody unless _tmp return _tmp end # HtmlBlockCloseTbody = "<" Spnl "/" ("tbody" | "TBODY") Spnl ">" def _HtmlBlockCloseTbody _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tbody") break if _tmp self.pos = _save1 _tmp = match_string("TBODY") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTbody unless _tmp return _tmp end # HtmlBlockTbody = HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody def _HtmlBlockTbody _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTbody) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTbody) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTbody) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTbody) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTbody unless _tmp return _tmp end # HtmlBlockOpenTd = "<" Spnl ("td" | "TD") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("td") break if _tmp self.pos = _save1 _tmp = match_string("TD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTd unless _tmp return _tmp end # HtmlBlockCloseTd = "<" Spnl "/" ("td" | "TD") Spnl ">" def _HtmlBlockCloseTd _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("td") break if _tmp self.pos = _save1 _tmp = match_string("TD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTd unless _tmp return _tmp end # HtmlBlockTd = HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd def _HtmlBlockTd _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTd) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTd) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTd) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTd) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTd unless _tmp return _tmp end # HtmlBlockOpenTfoot = "<" Spnl ("tfoot" | "TFOOT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTfoot _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tfoot") break if _tmp self.pos = _save1 _tmp = match_string("TFOOT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTfoot unless _tmp return _tmp end # HtmlBlockCloseTfoot = "<" Spnl "/" ("tfoot" | "TFOOT") Spnl ">" def _HtmlBlockCloseTfoot _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tfoot") break if _tmp self.pos = _save1 _tmp = match_string("TFOOT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTfoot unless _tmp return _tmp end # HtmlBlockTfoot = HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot def _HtmlBlockTfoot _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTfoot) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTfoot) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTfoot) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTfoot) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTfoot unless _tmp return _tmp end # HtmlBlockOpenTh = "<" Spnl ("th" | "TH") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTh _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("th") break if _tmp self.pos = _save1 _tmp = match_string("TH") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTh unless _tmp return _tmp end # HtmlBlockCloseTh = "<" Spnl "/" ("th" | "TH") Spnl ">" def _HtmlBlockCloseTh _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("th") break if _tmp self.pos = _save1 _tmp = match_string("TH") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTh unless _tmp return _tmp end # HtmlBlockTh = HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh def _HtmlBlockTh _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTh) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTh) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTh) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTh) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTh unless _tmp return _tmp end # HtmlBlockOpenThead = "<" Spnl ("thead" | "THEAD") Spnl HtmlAttribute* ">" def _HtmlBlockOpenThead _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("thead") break if _tmp self.pos = _save1 _tmp = match_string("THEAD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenThead unless _tmp return _tmp end # HtmlBlockCloseThead = "<" Spnl "/" ("thead" | "THEAD") Spnl ">" def _HtmlBlockCloseThead _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("thead") break if _tmp self.pos = _save1 _tmp = match_string("THEAD") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseThead unless _tmp return _tmp end # HtmlBlockThead = HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead def _HtmlBlockThead _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenThead) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockThead) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseThead) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseThead) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockThead unless _tmp return _tmp end # HtmlBlockOpenTr = "<" Spnl ("tr" | "TR") Spnl HtmlAttribute* ">" def _HtmlBlockOpenTr _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tr") break if _tmp self.pos = _save1 _tmp = match_string("TR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenTr unless _tmp return _tmp end # HtmlBlockCloseTr = "<" Spnl "/" ("tr" | "TR") Spnl ">" def _HtmlBlockCloseTr _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("tr") break if _tmp self.pos = _save1 _tmp = match_string("TR") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseTr unless _tmp return _tmp end # HtmlBlockTr = HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr def _HtmlBlockTr _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenTr) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # choice _tmp = apply(:_HtmlBlockTr) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_HtmlBlockCloseTr) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseTr) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockTr unless _tmp return _tmp end # HtmlBlockOpenScript = "<" Spnl ("script" | "SCRIPT") Spnl HtmlAttribute* ">" def _HtmlBlockOpenScript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("script") break if _tmp self.pos = _save1 _tmp = match_string("SCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockOpenScript unless _tmp return _tmp end # HtmlBlockCloseScript = "<" Spnl "/" ("script" | "SCRIPT") Spnl ">" def _HtmlBlockCloseScript _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("script") break if _tmp self.pos = _save1 _tmp = match_string("SCRIPT") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockCloseScript unless _tmp return _tmp end # HtmlBlockScript = HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript def _HtmlBlockScript _save = self.pos while true # sequence _tmp = apply(:_HtmlBlockOpenScript) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_HtmlBlockCloseScript) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockCloseScript) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockScript unless _tmp return _tmp end # HtmlBlockInTags = (HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript) def _HtmlBlockInTags _save = self.pos while true # choice _tmp = apply(:_HtmlBlockAddress) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockBlockquote) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockCenter) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDir) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDiv) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDl) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockFieldset) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockForm) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH1) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH2) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH3) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH4) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH5) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockH6) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockMenu) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockNoframes) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockNoscript) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockOl) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockP) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockPre) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTable) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockUl) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDd) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockDt) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockFrameset) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockLi) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTbody) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTd) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTfoot) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTh) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockThead) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockTr) break if _tmp self.pos = _save _tmp = apply(:_HtmlBlockScript) break if _tmp self.pos = _save break end # end choice set_failed_rule :_HtmlBlockInTags unless _tmp return _tmp end # HtmlBlock = < (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > BlankLine+ { if html? then RDoc::Markup::Raw.new text end } def _HtmlBlock _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos while true # choice _tmp = apply(:_HtmlBlockInTags) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlComment) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlBlockSelfClosing) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlUnclosed) break if _tmp self.pos = _save1 break end # end choice if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_BlankLine) if _tmp while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end @result = begin; if html? then RDoc::Markup::Raw.new text end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlock unless _tmp return _tmp end # HtmlUnclosed = "<" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl ">" def _HtmlUnclosed _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_HtmlUnclosedType) unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlUnclosed unless _tmp return _tmp end # HtmlUnclosedType = ("HR" | "hr") def _HtmlUnclosedType _save = self.pos while true # choice _tmp = match_string("HR") break if _tmp self.pos = _save _tmp = match_string("hr") break if _tmp self.pos = _save break end # end choice set_failed_rule :_HtmlUnclosedType unless _tmp return _tmp end # HtmlBlockSelfClosing = "<" Spnl HtmlBlockType Spnl HtmlAttribute* "/" Spnl ">" def _HtmlBlockSelfClosing _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_HtmlBlockType) unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlBlockSelfClosing unless _tmp return _tmp end # HtmlBlockType = ("ADDRESS" | "BLOCKQUOTE" | "CENTER" | "DD" | "DIR" | "DIV" | "DL" | "DT" | "FIELDSET" | "FORM" | "FRAMESET" | "H1" | "H2" | "H3" | "H4" | "H5" | "H6" | "HR" | "ISINDEX" | "LI" | "MENU" | "NOFRAMES" | "NOSCRIPT" | "OL" | "P" | "PRE" | "SCRIPT" | "TABLE" | "TBODY" | "TD" | "TFOOT" | "TH" | "THEAD" | "TR" | "UL" | "address" | "blockquote" | "center" | "dd" | "dir" | "div" | "dl" | "dt" | "fieldset" | "form" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "hr" | "isindex" | "li" | "menu" | "noframes" | "noscript" | "ol" | "p" | "pre" | "script" | "table" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "ul") def _HtmlBlockType _save = self.pos while true # choice _tmp = match_string("ADDRESS") break if _tmp self.pos = _save _tmp = match_string("BLOCKQUOTE") break if _tmp self.pos = _save _tmp = match_string("CENTER") break if _tmp self.pos = _save _tmp = match_string("DD") break if _tmp self.pos = _save _tmp = match_string("DIR") break if _tmp self.pos = _save _tmp = match_string("DIV") break if _tmp self.pos = _save _tmp = match_string("DL") break if _tmp self.pos = _save _tmp = match_string("DT") break if _tmp self.pos = _save _tmp = match_string("FIELDSET") break if _tmp self.pos = _save _tmp = match_string("FORM") break if _tmp self.pos = _save _tmp = match_string("FRAMESET") break if _tmp self.pos = _save _tmp = match_string("H1") break if _tmp self.pos = _save _tmp = match_string("H2") break if _tmp self.pos = _save _tmp = match_string("H3") break if _tmp self.pos = _save _tmp = match_string("H4") break if _tmp self.pos = _save _tmp = match_string("H5") break if _tmp self.pos = _save _tmp = match_string("H6") break if _tmp self.pos = _save _tmp = match_string("HR") break if _tmp self.pos = _save _tmp = match_string("ISINDEX") break if _tmp self.pos = _save _tmp = match_string("LI") break if _tmp self.pos = _save _tmp = match_string("MENU") break if _tmp self.pos = _save _tmp = match_string("NOFRAMES") break if _tmp self.pos = _save _tmp = match_string("NOSCRIPT") break if _tmp self.pos = _save _tmp = match_string("OL") break if _tmp self.pos = _save _tmp = match_string("P") break if _tmp self.pos = _save _tmp = match_string("PRE") break if _tmp self.pos = _save _tmp = match_string("SCRIPT") break if _tmp self.pos = _save _tmp = match_string("TABLE") break if _tmp self.pos = _save _tmp = match_string("TBODY") break if _tmp self.pos = _save _tmp = match_string("TD") break if _tmp self.pos = _save _tmp = match_string("TFOOT") break if _tmp self.pos = _save _tmp = match_string("TH") break if _tmp self.pos = _save _tmp = match_string("THEAD") break if _tmp self.pos = _save _tmp = match_string("TR") break if _tmp self.pos = _save _tmp = match_string("UL") break if _tmp self.pos = _save _tmp = match_string("address") break if _tmp self.pos = _save _tmp = match_string("blockquote") break if _tmp self.pos = _save _tmp = match_string("center") break if _tmp self.pos = _save _tmp = match_string("dd") break if _tmp self.pos = _save _tmp = match_string("dir") break if _tmp self.pos = _save _tmp = match_string("div") break if _tmp self.pos = _save _tmp = match_string("dl") break if _tmp self.pos = _save _tmp = match_string("dt") break if _tmp self.pos = _save _tmp = match_string("fieldset") break if _tmp self.pos = _save _tmp = match_string("form") break if _tmp self.pos = _save _tmp = match_string("frameset") break if _tmp self.pos = _save _tmp = match_string("h1") break if _tmp self.pos = _save _tmp = match_string("h2") break if _tmp self.pos = _save _tmp = match_string("h3") break if _tmp self.pos = _save _tmp = match_string("h4") break if _tmp self.pos = _save _tmp = match_string("h5") break if _tmp self.pos = _save _tmp = match_string("h6") break if _tmp self.pos = _save _tmp = match_string("hr") break if _tmp self.pos = _save _tmp = match_string("isindex") break if _tmp self.pos = _save _tmp = match_string("li") break if _tmp self.pos = _save _tmp = match_string("menu") break if _tmp self.pos = _save _tmp = match_string("noframes") break if _tmp self.pos = _save _tmp = match_string("noscript") break if _tmp self.pos = _save _tmp = match_string("ol") break if _tmp self.pos = _save _tmp = match_string("p") break if _tmp self.pos = _save _tmp = match_string("pre") break if _tmp self.pos = _save _tmp = match_string("script") break if _tmp self.pos = _save _tmp = match_string("table") break if _tmp self.pos = _save _tmp = match_string("tbody") break if _tmp self.pos = _save _tmp = match_string("td") break if _tmp self.pos = _save _tmp = match_string("tfoot") break if _tmp self.pos = _save _tmp = match_string("th") break if _tmp self.pos = _save _tmp = match_string("thead") break if _tmp self.pos = _save _tmp = match_string("tr") break if _tmp self.pos = _save _tmp = match_string("ul") break if _tmp self.pos = _save break end # end choice set_failed_rule :_HtmlBlockType unless _tmp return _tmp end # StyleOpen = "<" Spnl ("style" | "STYLE") Spnl HtmlAttribute* ">" def _StyleOpen _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("style") break if _tmp self.pos = _save1 _tmp = match_string("STYLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StyleOpen unless _tmp return _tmp end # StyleClose = "<" Spnl "/" ("style" | "STYLE") Spnl ">" def _StyleClose _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("/") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = match_string("style") break if _tmp self.pos = _save1 _tmp = match_string("STYLE") break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StyleClose unless _tmp return _tmp end # InStyleTags = StyleOpen (!StyleClose .)* StyleClose def _InStyleTags _save = self.pos while true # sequence _tmp = apply(:_StyleOpen) unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_StyleClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_StyleClose) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_InStyleTags unless _tmp return _tmp end # StyleBlock = < InStyleTags > BlankLine* { if css? then RDoc::Markup::Raw.new text end } def _StyleBlock _save = self.pos while true # sequence _text_start = self.pos _tmp = apply(:_InStyleTags) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; if css? then RDoc::Markup::Raw.new text end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StyleBlock unless _tmp return _tmp end # Inlines = (!Endline Inline:i { i } | Endline:c &Inline { c })+:chunks Endline? { chunks } def _Inlines _save = self.pos while true # sequence _save1 = self.pos _ary = [] _save2 = self.pos while true # choice _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_Endline) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_Inline) i = @result unless _tmp self.pos = _save3 break end @result = begin; i ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 _save5 = self.pos while true # sequence _tmp = apply(:_Endline) c = @result unless _tmp self.pos = _save5 break end _save6 = self.pos _tmp = apply(:_Inline) self.pos = _save6 unless _tmp self.pos = _save5 break end @result = begin; c ; end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice if _tmp _ary << @result while true _save7 = self.pos while true # choice _save8 = self.pos while true # sequence _save9 = self.pos _tmp = apply(:_Endline) _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _tmp = apply(:_Inline) i = @result unless _tmp self.pos = _save8 break end @result = begin; i ; end _tmp = true unless _tmp self.pos = _save8 end break end # end sequence break if _tmp self.pos = _save7 _save10 = self.pos while true # sequence _tmp = apply(:_Endline) c = @result unless _tmp self.pos = _save10 break end _save11 = self.pos _tmp = apply(:_Inline) self.pos = _save11 unless _tmp self.pos = _save10 break end @result = begin; c ; end _tmp = true unless _tmp self.pos = _save10 end break end # end sequence break if _tmp self.pos = _save7 break end # end choice _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end chunks = @result unless _tmp self.pos = _save break end _save12 = self.pos _tmp = apply(:_Endline) unless _tmp _tmp = true self.pos = _save12 end unless _tmp self.pos = _save break end @result = begin; chunks ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Inlines unless _tmp return _tmp end # Inline = (Str | Endline | UlOrStarLine | Space | Strong | Emph | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol) def _Inline _save = self.pos while true # choice _tmp = apply(:_Str) break if _tmp self.pos = _save _tmp = apply(:_Endline) break if _tmp self.pos = _save _tmp = apply(:_UlOrStarLine) break if _tmp self.pos = _save _tmp = apply(:_Space) break if _tmp self.pos = _save _tmp = apply(:_Strong) break if _tmp self.pos = _save _tmp = apply(:_Emph) break if _tmp self.pos = _save _tmp = apply(:_Image) break if _tmp self.pos = _save _tmp = apply(:_Link) break if _tmp self.pos = _save _tmp = apply(:_NoteReference) break if _tmp self.pos = _save _tmp = apply(:_InlineNote) break if _tmp self.pos = _save _tmp = apply(:_Code) break if _tmp self.pos = _save _tmp = apply(:_RawHtml) break if _tmp self.pos = _save _tmp = apply(:_Entity) break if _tmp self.pos = _save _tmp = apply(:_EscapedChar) break if _tmp self.pos = _save _tmp = apply(:_Symbol) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Inline unless _tmp return _tmp end # Space = Spacechar+ { " " } def _Space _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Spacechar) if _tmp while true _tmp = apply(:_Spacechar) break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; " " ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Space unless _tmp return _tmp end # Str = StartList:a < NormalChar+ > { a = text } (StrChunk:c { a << c })* { a } def _Str _save = self.pos while true # sequence _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos _tmp = apply(:_NormalChar) if _tmp while true _tmp = apply(:_NormalChar) break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; a = text ; end _tmp = true unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _tmp = apply(:_StrChunk) c = @result unless _tmp self.pos = _save3 break end @result = begin; a << c ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Str unless _tmp return _tmp end # StrChunk = < (NormalChar | "_"+ &Alphanumeric)+ > { text } def _StrChunk _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos _save2 = self.pos while true # choice _tmp = apply(:_NormalChar) break if _tmp self.pos = _save2 _save3 = self.pos while true # sequence _save4 = self.pos _tmp = match_string("_") if _tmp while true _tmp = match_string("_") break unless _tmp end _tmp = true else self.pos = _save4 end unless _tmp self.pos = _save3 break end _save5 = self.pos _tmp = apply(:_Alphanumeric) self.pos = _save5 unless _tmp self.pos = _save3 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice if _tmp while true _save6 = self.pos while true # choice _tmp = apply(:_NormalChar) break if _tmp self.pos = _save6 _save7 = self.pos while true # sequence _save8 = self.pos _tmp = match_string("_") if _tmp while true _tmp = match_string("_") break unless _tmp end _tmp = true else self.pos = _save8 end unless _tmp self.pos = _save7 break end _save9 = self.pos _tmp = apply(:_Alphanumeric) self.pos = _save9 unless _tmp self.pos = _save7 end break end # end sequence break if _tmp self.pos = _save6 break end # end choice break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StrChunk unless _tmp return _tmp end # EscapedChar = "\\" !Newline < /[:\\`|*_{}\[\]()#+.!><-]/ > { text } def _EscapedChar _save = self.pos while true # sequence _tmp = match_string("\\") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[:\\`|*_{}\[\]()#+.!><-])/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_EscapedChar unless _tmp return _tmp end # Entity = (HexEntity | DecEntity | CharEntity):a { a } def _Entity _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_HexEntity) break if _tmp self.pos = _save1 _tmp = apply(:_DecEntity) break if _tmp self.pos = _save1 _tmp = apply(:_CharEntity) break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Entity unless _tmp return _tmp end # Endline = (LineBreak | TerminalEndline | NormalEndline) def _Endline _save = self.pos while true # choice _tmp = apply(:_LineBreak) break if _tmp self.pos = _save _tmp = apply(:_TerminalEndline) break if _tmp self.pos = _save _tmp = apply(:_NormalEndline) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Endline unless _tmp return _tmp end # NormalEndline = Sp Newline !BlankLine !">" !AtxStart !(Line ("===" "="* | "---" "-"*) Newline) { "\n" } def _NormalEndline _save = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end _save1 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = apply(:_AtxStart) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save break end _save4 = self.pos _save5 = self.pos while true # sequence _tmp = apply(:_Line) unless _tmp self.pos = _save5 break end _save6 = self.pos while true # choice _save7 = self.pos while true # sequence _tmp = match_string("===") unless _tmp self.pos = _save7 break end while true _tmp = match_string("=") break unless _tmp end _tmp = true unless _tmp self.pos = _save7 end break end # end sequence break if _tmp self.pos = _save6 _save9 = self.pos while true # sequence _tmp = match_string("---") unless _tmp self.pos = _save9 break end while true _tmp = match_string("-") break unless _tmp end _tmp = true unless _tmp self.pos = _save9 end break end # end sequence break if _tmp self.pos = _save6 break end # end choice unless _tmp self.pos = _save5 break end _tmp = apply(:_Newline) unless _tmp self.pos = _save5 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save break end @result = begin; "\n" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_NormalEndline unless _tmp return _tmp end # TerminalEndline = Sp Newline Eof def _TerminalEndline _save = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end _tmp = apply(:_Eof) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TerminalEndline unless _tmp return _tmp end # LineBreak = " " NormalEndline { RDoc::Markup::HardBreak.new } def _LineBreak _save = self.pos while true # sequence _tmp = match_string(" ") unless _tmp self.pos = _save break end _tmp = apply(:_NormalEndline) unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::HardBreak.new ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_LineBreak unless _tmp return _tmp end # Symbol = < SpecialChar > { text } def _Symbol _save = self.pos while true # sequence _text_start = self.pos _tmp = apply(:_SpecialChar) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Symbol unless _tmp return _tmp end # UlOrStarLine = (UlLine | StarLine):a { a } def _UlOrStarLine _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_UlLine) break if _tmp self.pos = _save1 _tmp = apply(:_StarLine) break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_UlOrStarLine unless _tmp return _tmp end # StarLine = (< "****" "*"* > { text } | < Spacechar "*"+ &Spacechar > { text }) def _StarLine _save = self.pos while true # choice _save1 = self.pos while true # sequence _text_start = self.pos _save2 = self.pos while true # sequence _tmp = match_string("****") unless _tmp self.pos = _save2 break end while true _tmp = match_string("*") break unless _tmp end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save1 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save4 = self.pos while true # sequence _text_start = self.pos _save5 = self.pos while true # sequence _tmp = apply(:_Spacechar) unless _tmp self.pos = _save5 break end _save6 = self.pos _tmp = match_string("*") if _tmp while true _tmp = match_string("*") break unless _tmp end _tmp = true else self.pos = _save6 end unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = apply(:_Spacechar) self.pos = _save7 unless _tmp self.pos = _save5 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save4 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break if _tmp self.pos = _save break end # end choice set_failed_rule :_StarLine unless _tmp return _tmp end # UlLine = (< "____" "_"* > { text } | < Spacechar "_"+ &Spacechar > { text }) def _UlLine _save = self.pos while true # choice _save1 = self.pos while true # sequence _text_start = self.pos _save2 = self.pos while true # sequence _tmp = match_string("____") unless _tmp self.pos = _save2 break end while true _tmp = match_string("_") break unless _tmp end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save1 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save4 = self.pos while true # sequence _text_start = self.pos _save5 = self.pos while true # sequence _tmp = apply(:_Spacechar) unless _tmp self.pos = _save5 break end _save6 = self.pos _tmp = match_string("_") if _tmp while true _tmp = match_string("_") break unless _tmp end _tmp = true else self.pos = _save6 end unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = apply(:_Spacechar) self.pos = _save7 unless _tmp self.pos = _save5 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save4 break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break if _tmp self.pos = _save break end # end choice set_failed_rule :_UlLine unless _tmp return _tmp end # Emph = (EmphStar | EmphUl) def _Emph _save = self.pos while true # choice _tmp = apply(:_EmphStar) break if _tmp self.pos = _save _tmp = apply(:_EmphUl) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Emph unless _tmp return _tmp end # OneStarOpen = !StarLine "*" !Spacechar !Newline def _OneStarOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_StarLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("*") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneStarOpen unless _tmp return _tmp end # OneStarClose = !Spacechar !Newline Inline:a "*" { a } def _OneStarClose _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("*") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneStarClose unless _tmp return _tmp end # EmphStar = OneStarOpen StartList:a (!OneStarClose Inline:l { a << l })* OneStarClose:l { a << l } { emphasis a.join } def _EmphStar _save = self.pos while true # sequence _tmp = apply(:_OneStarOpen) unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_OneStarClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_OneStarClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; emphasis a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_EmphStar unless _tmp return _tmp end # OneUlOpen = !UlLine "_" !Spacechar !Newline def _OneUlOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_UlLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("_") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneUlOpen unless _tmp return _tmp end # OneUlClose = !Spacechar !Newline Inline:a "_" { a } def _OneUlClose _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("_") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OneUlClose unless _tmp return _tmp end # EmphUl = OneUlOpen StartList:a (!OneUlClose Inline:l { a << l })* OneUlClose:l { a << l } { emphasis a.join } def _EmphUl _save = self.pos while true # sequence _tmp = apply(:_OneUlOpen) unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_OneUlClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_OneUlClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; emphasis a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_EmphUl unless _tmp return _tmp end # Strong = (StrongStar | StrongUl) def _Strong _save = self.pos while true # choice _tmp = apply(:_StrongStar) break if _tmp self.pos = _save _tmp = apply(:_StrongUl) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Strong unless _tmp return _tmp end # TwoStarOpen = !StarLine "**" !Spacechar !Newline def _TwoStarOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_StarLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("**") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoStarOpen unless _tmp return _tmp end # TwoStarClose = !Spacechar !Newline Inline:a "**" { a } def _TwoStarClose _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("**") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoStarClose unless _tmp return _tmp end # StrongStar = TwoStarOpen StartList:a (!TwoStarClose Inline:l { a << l })* TwoStarClose:l { a << l } { strong a.join } def _StrongStar _save = self.pos while true # sequence _tmp = apply(:_TwoStarOpen) unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_TwoStarClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_TwoStarClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; strong a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StrongStar unless _tmp return _tmp end # TwoUlOpen = !UlLine "__" !Spacechar !Newline def _TwoUlOpen _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_UlLine) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("__") unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _save3 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoUlOpen unless _tmp return _tmp end # TwoUlClose = !Spacechar !Newline Inline:a "__" { a } def _TwoUlClose _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = apply(:_Inline) a = @result unless _tmp self.pos = _save break end _tmp = match_string("__") unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TwoUlClose unless _tmp return _tmp end # StrongUl = TwoUlOpen StartList:a (!TwoUlClose Inline:i { a << i })* TwoUlClose:l { a << l } { strong a.join } def _StrongUl _save = self.pos while true # sequence _tmp = apply(:_TwoUlOpen) unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_TwoUlClose) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_Inline) i = @result unless _tmp self.pos = _save2 break end @result = begin; a << i ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = apply(:_TwoUlClose) l = @result unless _tmp self.pos = _save break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; strong a.join ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StrongUl unless _tmp return _tmp end # Image = "!" (ExplicitLink | ReferenceLink):a { a } def _Image _save = self.pos while true # sequence _tmp = match_string("!") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _tmp = apply(:_ExplicitLink) break if _tmp self.pos = _save1 _tmp = apply(:_ReferenceLink) break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Image unless _tmp return _tmp end # Link = (ExplicitLink | ReferenceLink | AutoLink) def _Link _save = self.pos while true # choice _tmp = apply(:_ExplicitLink) break if _tmp self.pos = _save _tmp = apply(:_ReferenceLink) break if _tmp self.pos = _save _tmp = apply(:_AutoLink) break if _tmp self.pos = _save break end # end choice set_failed_rule :_Link unless _tmp return _tmp end # ReferenceLink = (ReferenceLinkDouble | ReferenceLinkSingle) def _ReferenceLink _save = self.pos while true # choice _tmp = apply(:_ReferenceLinkDouble) break if _tmp self.pos = _save _tmp = apply(:_ReferenceLinkSingle) break if _tmp self.pos = _save break end # end choice set_failed_rule :_ReferenceLink unless _tmp return _tmp end # ReferenceLinkDouble = Label:content < Spnl > !"[]" Label:label { link_to content, label, text } def _ReferenceLinkDouble _save = self.pos while true # sequence _tmp = apply(:_Label) content = @result unless _tmp self.pos = _save break end _text_start = self.pos _tmp = apply(:_Spnl) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("[]") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Label) label = @result unless _tmp self.pos = _save break end @result = begin; link_to content, label, text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ReferenceLinkDouble unless _tmp return _tmp end # ReferenceLinkSingle = Label:content < (Spnl "[]")? > { link_to content, content, text } def _ReferenceLinkSingle _save = self.pos while true # sequence _tmp = apply(:_Label) content = @result unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos _save2 = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save2 break end _tmp = match_string("[]") unless _tmp self.pos = _save2 end break end # end sequence unless _tmp _tmp = true self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; link_to content, content, text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ReferenceLinkSingle unless _tmp return _tmp end # ExplicitLink = Label:l Spnl "(" Sp Source:s Spnl Title Sp ")" { "{#{l}}[#{s}]" } def _ExplicitLink _save = self.pos while true # sequence _tmp = apply(:_Label) l = @result unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("(") unless _tmp self.pos = _save break end _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = apply(:_Source) s = @result unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_Title) unless _tmp self.pos = _save break end _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = match_string(")") unless _tmp self.pos = _save break end @result = begin; "{#{l}}[#{s}]" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ExplicitLink unless _tmp return _tmp end # Source = ("<" < SourceContents > ">" | < SourceContents >) { text } def _Source _save = self.pos while true # sequence _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save2 break end _text_start = self.pos _tmp = apply(:_SourceContents) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save2 break end _tmp = match_string(">") unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _text_start = self.pos _tmp = apply(:_SourceContents) if _tmp text = get_text(_text_start) end break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Source unless _tmp return _tmp end # SourceContents = (((!"(" !")" !">" Nonspacechar)+ | "(" SourceContents ")")* | "") def _SourceContents _save = self.pos while true # choice while true _save2 = self.pos while true # choice _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = match_string("(") _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _save6 = self.pos _tmp = match_string(")") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save4 break end _save7 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save4 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string("(") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _save10 = self.pos _tmp = match_string(")") _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save8 break end _save11 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save8 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save8 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end break if _tmp self.pos = _save2 _save12 = self.pos while true # sequence _tmp = match_string("(") unless _tmp self.pos = _save12 break end _tmp = apply(:_SourceContents) unless _tmp self.pos = _save12 break end _tmp = match_string(")") unless _tmp self.pos = _save12 end break end # end sequence break if _tmp self.pos = _save2 break end # end choice break unless _tmp end _tmp = true break if _tmp self.pos = _save _tmp = match_string("") break if _tmp self.pos = _save break end # end choice set_failed_rule :_SourceContents unless _tmp return _tmp end # Title = (TitleSingle | TitleDouble | ""):a { a } def _Title _save = self.pos while true # sequence _save1 = self.pos while true # choice _tmp = apply(:_TitleSingle) break if _tmp self.pos = _save1 _tmp = apply(:_TitleDouble) break if _tmp self.pos = _save1 _tmp = match_string("") break if _tmp self.pos = _save1 break end # end choice a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Title unless _tmp return _tmp end # TitleSingle = "'" (!("'" Sp (")" | Newline)) .)* "'" def _TitleSingle _save = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save4 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save4 break end _save5 = self.pos while true # choice _tmp = match_string(")") break if _tmp self.pos = _save5 _tmp = apply(:_Newline) break if _tmp self.pos = _save5 break end # end choice unless _tmp self.pos = _save4 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("'") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TitleSingle unless _tmp return _tmp end # TitleDouble = "\"" (!("\"" Sp (")" | Newline)) .)* "\"" def _TitleDouble _save = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save break end while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save4 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save4 break end _save5 = self.pos while true # choice _tmp = match_string(")") break if _tmp self.pos = _save5 _tmp = apply(:_Newline) break if _tmp self.pos = _save5 break end # end choice unless _tmp self.pos = _save4 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("\"") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_TitleDouble unless _tmp return _tmp end # AutoLink = (AutoLinkUrl | AutoLinkEmail) def _AutoLink _save = self.pos while true # choice _tmp = apply(:_AutoLinkUrl) break if _tmp self.pos = _save _tmp = apply(:_AutoLinkEmail) break if _tmp self.pos = _save break end # end choice set_failed_rule :_AutoLink unless _tmp return _tmp end # AutoLinkUrl = "<" < /[A-Za-z]+/ "://" (!Newline !">" .)+ > ">" { text } def _AutoLinkUrl _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos while true # sequence _tmp = scan(/\A(?-mix:[A-Za-z]+)/) unless _tmp self.pos = _save1 break end _tmp = match_string("://") unless _tmp self.pos = _save1 break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _save5 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save6 = self.pos while true # sequence _save7 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _save8 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save6 break end _tmp = get_byte unless _tmp self.pos = _save6 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save1 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AutoLinkUrl unless _tmp return _tmp end # AutoLinkEmail = "<" "mailto:"? < /[\w+.\/!%~$-]+/i "@" (!Newline !">" .)+ > ">" { "mailto:#{text}" } def _AutoLinkEmail _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("mailto:") unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _text_start = self.pos _save2 = self.pos while true # sequence _tmp = scan(/\A(?i-mx:[\w+.\/!%~$-]+)/) unless _tmp self.pos = _save2 break end _tmp = match_string("@") unless _tmp self.pos = _save2 break end _save3 = self.pos _save4 = self.pos while true # sequence _save5 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _save6 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save4 break end _tmp = get_byte unless _tmp self.pos = _save4 end break end # end sequence if _tmp while true _save7 = self.pos while true # sequence _save8 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save7 break end _save9 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save7 break end _tmp = get_byte unless _tmp self.pos = _save7 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save3 end unless _tmp self.pos = _save2 end break end # end sequence if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save break end @result = begin; "mailto:#{text}" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_AutoLinkEmail unless _tmp return _tmp end # Reference = NonindentSpace !"[]" Label:label ":" Spnl RefSrc:link RefTitle BlankLine+ { # TODO use title reference label, link nil } def _Reference _save = self.pos while true # sequence _tmp = apply(:_NonindentSpace) unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("[]") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Label) label = @result unless _tmp self.pos = _save break end _tmp = match_string(":") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = apply(:_RefSrc) link = @result unless _tmp self.pos = _save break end _tmp = apply(:_RefTitle) unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_BlankLine) if _tmp while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end @result = begin; # TODO use title reference label, link nil ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Reference unless _tmp return _tmp end # Label = "[" (!"^" &{ notes? } | &. &{ !notes? }) StartList:a (!"]" Inline:l { a << l })* "]" { a.join.gsub(/\s+/, ' ') } def _Label _save = self.pos while true # sequence _tmp = match_string("[") unless _tmp self.pos = _save break end _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _save3 = self.pos _tmp = match_string("^") _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _save4 = self.pos _tmp = begin; notes? ; end self.pos = _save4 unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _save5 = self.pos while true # sequence _save6 = self.pos _tmp = get_byte self.pos = _save6 unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = begin; !notes? ; end self.pos = _save7 unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end while true _save9 = self.pos while true # sequence _save10 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save9 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save9 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save9 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("]") unless _tmp self.pos = _save break end @result = begin; a.join.gsub(/\s+/, ' ') ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Label unless _tmp return _tmp end # RefSrc = < Nonspacechar+ > { text } def _RefSrc _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos _tmp = apply(:_Nonspacechar) if _tmp while true _tmp = apply(:_Nonspacechar) break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefSrc unless _tmp return _tmp end # RefTitle = (RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle) def _RefTitle _save = self.pos while true # choice _tmp = apply(:_RefTitleSingle) break if _tmp self.pos = _save _tmp = apply(:_RefTitleDouble) break if _tmp self.pos = _save _tmp = apply(:_RefTitleParens) break if _tmp self.pos = _save _tmp = apply(:_EmptyTitle) break if _tmp self.pos = _save break end # end choice set_failed_rule :_RefTitle unless _tmp return _tmp end # EmptyTitle = "" def _EmptyTitle _tmp = match_string("") set_failed_rule :_EmptyTitle unless _tmp return _tmp end # RefTitleSingle = Spnl "'" < (!("'" Sp Newline | Newline) .)* > "'" { text } def _RefTitleSingle _save = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("'") unless _tmp self.pos = _save break end _text_start = self.pos while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save5 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save5 break end _tmp = apply(:_Newline) unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save4 _tmp = apply(:_Newline) break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string("'") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefTitleSingle unless _tmp return _tmp end # RefTitleDouble = Spnl "\"" < (!("\"" Sp Newline | Newline) .)* > "\"" { text } def _RefTitleDouble _save = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("\"") unless _tmp self.pos = _save break end _text_start = self.pos while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save5 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save5 break end _tmp = apply(:_Newline) unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save4 _tmp = apply(:_Newline) break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string("\"") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefTitleDouble unless _tmp return _tmp end # RefTitleParens = Spnl "(" < (!(")" Sp Newline | Newline) .)* > ")" { text } def _RefTitleParens _save = self.pos while true # sequence _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string("(") unless _tmp self.pos = _save break end _text_start = self.pos while true _save2 = self.pos while true # sequence _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos while true # sequence _tmp = match_string(")") unless _tmp self.pos = _save5 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save5 break end _tmp = apply(:_Newline) unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save4 _tmp = apply(:_Newline) break if _tmp self.pos = _save4 break end # end choice _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(")") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RefTitleParens unless _tmp return _tmp end # References = (Reference | SkipBlock)* def _References while true _save1 = self.pos while true # choice _tmp = apply(:_Reference) break if _tmp self.pos = _save1 _tmp = apply(:_SkipBlock) break if _tmp self.pos = _save1 break end # end choice break unless _tmp end _tmp = true set_failed_rule :_References unless _tmp return _tmp end # Ticks1 = "`" !"`" def _Ticks1 _save = self.pos while true # sequence _tmp = match_string("`") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks1 unless _tmp return _tmp end # Ticks2 = "``" !"`" def _Ticks2 _save = self.pos while true # sequence _tmp = match_string("``") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks2 unless _tmp return _tmp end # Ticks3 = "```" !"`" def _Ticks3 _save = self.pos while true # sequence _tmp = match_string("```") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks3 unless _tmp return _tmp end # Ticks4 = "````" !"`" def _Ticks4 _save = self.pos while true # sequence _tmp = match_string("````") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks4 unless _tmp return _tmp end # Ticks5 = "`````" !"`" def _Ticks5 _save = self.pos while true # sequence _tmp = match_string("`````") unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Ticks5 unless _tmp return _tmp end # Code = (Ticks1 Sp < ((!"`" Nonspacechar)+ | !Ticks1 "`"+ | !(Sp Ticks1) (Spacechar | Newline !BlankLine))+ > Sp Ticks1 | Ticks2 Sp < ((!"`" Nonspacechar)+ | !Ticks2 "`"+ | !(Sp Ticks2) (Spacechar | Newline !BlankLine))+ > Sp Ticks2 | Ticks3 Sp < ((!"`" Nonspacechar)+ | !Ticks3 "`"+ | !(Sp Ticks3) (Spacechar | Newline !BlankLine))+ > Sp Ticks3 | Ticks4 Sp < ((!"`" Nonspacechar)+ | !Ticks4 "`"+ | !(Sp Ticks4) (Spacechar | Newline !BlankLine))+ > Sp Ticks4 | Ticks5 Sp < ((!"`" Nonspacechar)+ | !Ticks5 "`"+ | !(Sp Ticks5) (Spacechar | Newline !BlankLine))+ > Sp Ticks5) { "#{text}" } def _Code _save = self.pos while true # sequence _save1 = self.pos while true # choice _save2 = self.pos while true # sequence _tmp = apply(:_Ticks1) unless _tmp self.pos = _save2 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save2 break end _text_start = self.pos _save3 = self.pos _save4 = self.pos while true # choice _save5 = self.pos _save6 = self.pos while true # sequence _save7 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save6 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save6 end break end # end sequence if _tmp while true _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save8 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save5 end break if _tmp self.pos = _save4 _save10 = self.pos while true # sequence _save11 = self.pos _tmp = apply(:_Ticks1) _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save10 break end _save12 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save12 end unless _tmp self.pos = _save10 end break end # end sequence break if _tmp self.pos = _save4 _save13 = self.pos while true # sequence _save14 = self.pos _save15 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save15 break end _tmp = apply(:_Ticks1) unless _tmp self.pos = _save15 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save14 unless _tmp self.pos = _save13 break end _save16 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save16 _save17 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save17 break end _save18 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save18 unless _tmp self.pos = _save17 end break end # end sequence break if _tmp self.pos = _save16 break end # end choice unless _tmp self.pos = _save13 end break end # end sequence break if _tmp self.pos = _save4 break end # end choice if _tmp while true _save19 = self.pos while true # choice _save20 = self.pos _save21 = self.pos while true # sequence _save22 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save22 unless _tmp self.pos = _save21 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save21 end break end # end sequence if _tmp while true _save23 = self.pos while true # sequence _save24 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save24 unless _tmp self.pos = _save23 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save23 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save20 end break if _tmp self.pos = _save19 _save25 = self.pos while true # sequence _save26 = self.pos _tmp = apply(:_Ticks1) _tmp = _tmp ? nil : true self.pos = _save26 unless _tmp self.pos = _save25 break end _save27 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save27 end unless _tmp self.pos = _save25 end break end # end sequence break if _tmp self.pos = _save19 _save28 = self.pos while true # sequence _save29 = self.pos _save30 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save30 break end _tmp = apply(:_Ticks1) unless _tmp self.pos = _save30 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save29 unless _tmp self.pos = _save28 break end _save31 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save31 _save32 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save32 break end _save33 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save33 unless _tmp self.pos = _save32 end break end # end sequence break if _tmp self.pos = _save31 break end # end choice unless _tmp self.pos = _save28 end break end # end sequence break if _tmp self.pos = _save19 break end # end choice break unless _tmp end _tmp = true else self.pos = _save3 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save2 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save2 break end _tmp = apply(:_Ticks1) unless _tmp self.pos = _save2 end break end # end sequence break if _tmp self.pos = _save1 _save34 = self.pos while true # sequence _tmp = apply(:_Ticks2) unless _tmp self.pos = _save34 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save34 break end _text_start = self.pos _save35 = self.pos _save36 = self.pos while true # choice _save37 = self.pos _save38 = self.pos while true # sequence _save39 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save39 unless _tmp self.pos = _save38 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save38 end break end # end sequence if _tmp while true _save40 = self.pos while true # sequence _save41 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save41 unless _tmp self.pos = _save40 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save40 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save37 end break if _tmp self.pos = _save36 _save42 = self.pos while true # sequence _save43 = self.pos _tmp = apply(:_Ticks2) _tmp = _tmp ? nil : true self.pos = _save43 unless _tmp self.pos = _save42 break end _save44 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save44 end unless _tmp self.pos = _save42 end break end # end sequence break if _tmp self.pos = _save36 _save45 = self.pos while true # sequence _save46 = self.pos _save47 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save47 break end _tmp = apply(:_Ticks2) unless _tmp self.pos = _save47 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save46 unless _tmp self.pos = _save45 break end _save48 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save48 _save49 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save49 break end _save50 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save50 unless _tmp self.pos = _save49 end break end # end sequence break if _tmp self.pos = _save48 break end # end choice unless _tmp self.pos = _save45 end break end # end sequence break if _tmp self.pos = _save36 break end # end choice if _tmp while true _save51 = self.pos while true # choice _save52 = self.pos _save53 = self.pos while true # sequence _save54 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save54 unless _tmp self.pos = _save53 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save53 end break end # end sequence if _tmp while true _save55 = self.pos while true # sequence _save56 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save56 unless _tmp self.pos = _save55 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save55 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save52 end break if _tmp self.pos = _save51 _save57 = self.pos while true # sequence _save58 = self.pos _tmp = apply(:_Ticks2) _tmp = _tmp ? nil : true self.pos = _save58 unless _tmp self.pos = _save57 break end _save59 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save59 end unless _tmp self.pos = _save57 end break end # end sequence break if _tmp self.pos = _save51 _save60 = self.pos while true # sequence _save61 = self.pos _save62 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save62 break end _tmp = apply(:_Ticks2) unless _tmp self.pos = _save62 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save61 unless _tmp self.pos = _save60 break end _save63 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save63 _save64 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save64 break end _save65 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save65 unless _tmp self.pos = _save64 end break end # end sequence break if _tmp self.pos = _save63 break end # end choice unless _tmp self.pos = _save60 end break end # end sequence break if _tmp self.pos = _save51 break end # end choice break unless _tmp end _tmp = true else self.pos = _save35 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save34 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save34 break end _tmp = apply(:_Ticks2) unless _tmp self.pos = _save34 end break end # end sequence break if _tmp self.pos = _save1 _save66 = self.pos while true # sequence _tmp = apply(:_Ticks3) unless _tmp self.pos = _save66 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save66 break end _text_start = self.pos _save67 = self.pos _save68 = self.pos while true # choice _save69 = self.pos _save70 = self.pos while true # sequence _save71 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save71 unless _tmp self.pos = _save70 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save70 end break end # end sequence if _tmp while true _save72 = self.pos while true # sequence _save73 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save73 unless _tmp self.pos = _save72 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save72 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save69 end break if _tmp self.pos = _save68 _save74 = self.pos while true # sequence _save75 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save75 unless _tmp self.pos = _save74 break end _save76 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save76 end unless _tmp self.pos = _save74 end break end # end sequence break if _tmp self.pos = _save68 _save77 = self.pos while true # sequence _save78 = self.pos _save79 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save79 break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save79 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save78 unless _tmp self.pos = _save77 break end _save80 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save80 _save81 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save81 break end _save82 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save82 unless _tmp self.pos = _save81 end break end # end sequence break if _tmp self.pos = _save80 break end # end choice unless _tmp self.pos = _save77 end break end # end sequence break if _tmp self.pos = _save68 break end # end choice if _tmp while true _save83 = self.pos while true # choice _save84 = self.pos _save85 = self.pos while true # sequence _save86 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save86 unless _tmp self.pos = _save85 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save85 end break end # end sequence if _tmp while true _save87 = self.pos while true # sequence _save88 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save88 unless _tmp self.pos = _save87 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save87 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save84 end break if _tmp self.pos = _save83 _save89 = self.pos while true # sequence _save90 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save90 unless _tmp self.pos = _save89 break end _save91 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save91 end unless _tmp self.pos = _save89 end break end # end sequence break if _tmp self.pos = _save83 _save92 = self.pos while true # sequence _save93 = self.pos _save94 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save94 break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save94 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save93 unless _tmp self.pos = _save92 break end _save95 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save95 _save96 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save96 break end _save97 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save97 unless _tmp self.pos = _save96 end break end # end sequence break if _tmp self.pos = _save95 break end # end choice unless _tmp self.pos = _save92 end break end # end sequence break if _tmp self.pos = _save83 break end # end choice break unless _tmp end _tmp = true else self.pos = _save67 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save66 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save66 break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save66 end break end # end sequence break if _tmp self.pos = _save1 _save98 = self.pos while true # sequence _tmp = apply(:_Ticks4) unless _tmp self.pos = _save98 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save98 break end _text_start = self.pos _save99 = self.pos _save100 = self.pos while true # choice _save101 = self.pos _save102 = self.pos while true # sequence _save103 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save103 unless _tmp self.pos = _save102 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save102 end break end # end sequence if _tmp while true _save104 = self.pos while true # sequence _save105 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save105 unless _tmp self.pos = _save104 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save104 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save101 end break if _tmp self.pos = _save100 _save106 = self.pos while true # sequence _save107 = self.pos _tmp = apply(:_Ticks4) _tmp = _tmp ? nil : true self.pos = _save107 unless _tmp self.pos = _save106 break end _save108 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save108 end unless _tmp self.pos = _save106 end break end # end sequence break if _tmp self.pos = _save100 _save109 = self.pos while true # sequence _save110 = self.pos _save111 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save111 break end _tmp = apply(:_Ticks4) unless _tmp self.pos = _save111 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save110 unless _tmp self.pos = _save109 break end _save112 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save112 _save113 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save113 break end _save114 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save114 unless _tmp self.pos = _save113 end break end # end sequence break if _tmp self.pos = _save112 break end # end choice unless _tmp self.pos = _save109 end break end # end sequence break if _tmp self.pos = _save100 break end # end choice if _tmp while true _save115 = self.pos while true # choice _save116 = self.pos _save117 = self.pos while true # sequence _save118 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save118 unless _tmp self.pos = _save117 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save117 end break end # end sequence if _tmp while true _save119 = self.pos while true # sequence _save120 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save120 unless _tmp self.pos = _save119 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save119 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save116 end break if _tmp self.pos = _save115 _save121 = self.pos while true # sequence _save122 = self.pos _tmp = apply(:_Ticks4) _tmp = _tmp ? nil : true self.pos = _save122 unless _tmp self.pos = _save121 break end _save123 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save123 end unless _tmp self.pos = _save121 end break end # end sequence break if _tmp self.pos = _save115 _save124 = self.pos while true # sequence _save125 = self.pos _save126 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save126 break end _tmp = apply(:_Ticks4) unless _tmp self.pos = _save126 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save125 unless _tmp self.pos = _save124 break end _save127 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save127 _save128 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save128 break end _save129 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save129 unless _tmp self.pos = _save128 end break end # end sequence break if _tmp self.pos = _save127 break end # end choice unless _tmp self.pos = _save124 end break end # end sequence break if _tmp self.pos = _save115 break end # end choice break unless _tmp end _tmp = true else self.pos = _save99 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save98 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save98 break end _tmp = apply(:_Ticks4) unless _tmp self.pos = _save98 end break end # end sequence break if _tmp self.pos = _save1 _save130 = self.pos while true # sequence _tmp = apply(:_Ticks5) unless _tmp self.pos = _save130 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save130 break end _text_start = self.pos _save131 = self.pos _save132 = self.pos while true # choice _save133 = self.pos _save134 = self.pos while true # sequence _save135 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save135 unless _tmp self.pos = _save134 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save134 end break end # end sequence if _tmp while true _save136 = self.pos while true # sequence _save137 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save137 unless _tmp self.pos = _save136 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save136 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save133 end break if _tmp self.pos = _save132 _save138 = self.pos while true # sequence _save139 = self.pos _tmp = apply(:_Ticks5) _tmp = _tmp ? nil : true self.pos = _save139 unless _tmp self.pos = _save138 break end _save140 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save140 end unless _tmp self.pos = _save138 end break end # end sequence break if _tmp self.pos = _save132 _save141 = self.pos while true # sequence _save142 = self.pos _save143 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save143 break end _tmp = apply(:_Ticks5) unless _tmp self.pos = _save143 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save142 unless _tmp self.pos = _save141 break end _save144 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save144 _save145 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save145 break end _save146 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save146 unless _tmp self.pos = _save145 end break end # end sequence break if _tmp self.pos = _save144 break end # end choice unless _tmp self.pos = _save141 end break end # end sequence break if _tmp self.pos = _save132 break end # end choice if _tmp while true _save147 = self.pos while true # choice _save148 = self.pos _save149 = self.pos while true # sequence _save150 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save150 unless _tmp self.pos = _save149 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save149 end break end # end sequence if _tmp while true _save151 = self.pos while true # sequence _save152 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save152 unless _tmp self.pos = _save151 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save151 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save148 end break if _tmp self.pos = _save147 _save153 = self.pos while true # sequence _save154 = self.pos _tmp = apply(:_Ticks5) _tmp = _tmp ? nil : true self.pos = _save154 unless _tmp self.pos = _save153 break end _save155 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save155 end unless _tmp self.pos = _save153 end break end # end sequence break if _tmp self.pos = _save147 _save156 = self.pos while true # sequence _save157 = self.pos _save158 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save158 break end _tmp = apply(:_Ticks5) unless _tmp self.pos = _save158 end break end # end sequence _tmp = _tmp ? nil : true self.pos = _save157 unless _tmp self.pos = _save156 break end _save159 = self.pos while true # choice _tmp = apply(:_Spacechar) break if _tmp self.pos = _save159 _save160 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save160 break end _save161 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save161 unless _tmp self.pos = _save160 end break end # end sequence break if _tmp self.pos = _save159 break end # end choice unless _tmp self.pos = _save156 end break end # end sequence break if _tmp self.pos = _save147 break end # end choice break unless _tmp end _tmp = true else self.pos = _save131 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save130 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save130 break end _tmp = apply(:_Ticks5) unless _tmp self.pos = _save130 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end @result = begin; "#{text}" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Code unless _tmp return _tmp end # RawHtml = < (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end } def _RawHtml _save = self.pos while true # sequence _text_start = self.pos _save1 = self.pos while true # choice _tmp = apply(:_HtmlComment) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlBlockScript) break if _tmp self.pos = _save1 _tmp = apply(:_HtmlTag) break if _tmp self.pos = _save1 break end # end choice if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; if html? then text else '' end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawHtml unless _tmp return _tmp end # BlankLine = Sp Newline { "\n" } def _BlankLine _save = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end @result = begin; "\n" ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_BlankLine unless _tmp return _tmp end # Quoted = ("\"" (!"\"" .)* "\"" | "'" (!"'" .)* "'") def _Quoted _save = self.pos while true # choice _save1 = self.pos while true # sequence _tmp = match_string("\"") unless _tmp self.pos = _save1 break end while true _save3 = self.pos while true # sequence _save4 = self.pos _tmp = match_string("\"") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = get_byte unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save1 break end _tmp = match_string("\"") unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save5 = self.pos while true # sequence _tmp = match_string("'") unless _tmp self.pos = _save5 break end while true _save7 = self.pos while true # sequence _save8 = self.pos _tmp = match_string("'") _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save7 break end _tmp = get_byte unless _tmp self.pos = _save7 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save5 break end _tmp = match_string("'") unless _tmp self.pos = _save5 end break end # end sequence break if _tmp self.pos = _save break end # end choice set_failed_rule :_Quoted unless _tmp return _tmp end # HtmlAttribute = (AlphanumericAscii | "-")+ Spnl ("=" Spnl (Quoted | (!">" Nonspacechar)+))? Spnl def _HtmlAttribute _save = self.pos while true # sequence _save1 = self.pos _save2 = self.pos while true # choice _tmp = apply(:_AlphanumericAscii) break if _tmp self.pos = _save2 _tmp = match_string("-") break if _tmp self.pos = _save2 break end # end choice if _tmp while true _save3 = self.pos while true # choice _tmp = apply(:_AlphanumericAscii) break if _tmp self.pos = _save3 _tmp = match_string("-") break if _tmp self.pos = _save3 break end # end choice break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save4 = self.pos _save5 = self.pos while true # sequence _tmp = match_string("=") unless _tmp self.pos = _save5 break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save5 break end _save6 = self.pos while true # choice _tmp = apply(:_Quoted) break if _tmp self.pos = _save6 _save7 = self.pos _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save8 end break end # end sequence if _tmp while true _save10 = self.pos while true # sequence _save11 = self.pos _tmp = match_string(">") _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save10 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save10 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save7 end break if _tmp self.pos = _save6 break end # end choice unless _tmp self.pos = _save5 end break end # end sequence unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlAttribute unless _tmp return _tmp end # HtmlComment = "" .)* "-->" def _HtmlComment _save = self.pos while true # sequence _tmp = match_string("") _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _tmp = match_string("-->") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlComment unless _tmp return _tmp end # HtmlTag = "<" Spnl "/"? AlphanumericAscii+ Spnl HtmlAttribute* "/"? Spnl ">" def _HtmlTag _save = self.pos while true # sequence _tmp = match_string("<") unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _save1 = self.pos _tmp = match_string("/") unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_AlphanumericAscii) if _tmp while true _tmp = apply(:_AlphanumericAscii) break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end while true _tmp = apply(:_HtmlAttribute) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end _save4 = self.pos _tmp = match_string("/") unless _tmp _tmp = true self.pos = _save4 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _tmp = match_string(">") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HtmlTag unless _tmp return _tmp end # Eof = !. def _Eof _save = self.pos _tmp = get_byte _tmp = _tmp ? nil : true self.pos = _save set_failed_rule :_Eof unless _tmp return _tmp end # Nonspacechar = !Spacechar !Newline . def _Nonspacechar _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Spacechar) _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save2 unless _tmp self.pos = _save break end _tmp = get_byte unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Nonspacechar unless _tmp return _tmp end # Sp = Spacechar* def _Sp while true _tmp = apply(:_Spacechar) break unless _tmp end _tmp = true set_failed_rule :_Sp unless _tmp return _tmp end # Spnl = Sp (Newline Sp)? def _Spnl _save = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _tmp = apply(:_Newline) unless _tmp self.pos = _save2 break end _tmp = apply(:_Sp) unless _tmp self.pos = _save2 end break end # end sequence unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Spnl unless _tmp return _tmp end # SpecialChar = ("*" | "_" | "`" | "&" | "[" | "]" | "(" | ")" | "<" | "!" | "#" | "\\" | "'" | "\"" | ExtendedSpecialChar) def _SpecialChar _save = self.pos while true # choice _tmp = match_string("*") break if _tmp self.pos = _save _tmp = match_string("_") break if _tmp self.pos = _save _tmp = match_string("`") break if _tmp self.pos = _save _tmp = match_string("&") break if _tmp self.pos = _save _tmp = match_string("[") break if _tmp self.pos = _save _tmp = match_string("]") break if _tmp self.pos = _save _tmp = match_string("(") break if _tmp self.pos = _save _tmp = match_string(")") break if _tmp self.pos = _save _tmp = match_string("<") break if _tmp self.pos = _save _tmp = match_string("!") break if _tmp self.pos = _save _tmp = match_string("#") break if _tmp self.pos = _save _tmp = match_string("\\") break if _tmp self.pos = _save _tmp = match_string("'") break if _tmp self.pos = _save _tmp = match_string("\"") break if _tmp self.pos = _save _tmp = apply(:_ExtendedSpecialChar) break if _tmp self.pos = _save break end # end choice set_failed_rule :_SpecialChar unless _tmp return _tmp end # NormalChar = !(SpecialChar | Spacechar | Newline) . def _NormalChar _save = self.pos while true # sequence _save1 = self.pos _save2 = self.pos while true # choice _tmp = apply(:_SpecialChar) break if _tmp self.pos = _save2 _tmp = apply(:_Spacechar) break if _tmp self.pos = _save2 _tmp = apply(:_Newline) break if _tmp self.pos = _save2 break end # end choice _tmp = _tmp ? nil : true self.pos = _save1 unless _tmp self.pos = _save break end _tmp = get_byte unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_NormalChar unless _tmp return _tmp end # Digit = [0-9] def _Digit _save = self.pos _tmp = get_byte if _tmp unless _tmp >= 48 and _tmp <= 57 self.pos = _save _tmp = nil end end set_failed_rule :_Digit unless _tmp return _tmp end # Alphanumeric = %literals.Alphanumeric def _Alphanumeric _tmp = @_grammar_literals.external_invoke(self, :_Alphanumeric) set_failed_rule :_Alphanumeric unless _tmp return _tmp end # AlphanumericAscii = %literals.AlphanumericAscii def _AlphanumericAscii _tmp = @_grammar_literals.external_invoke(self, :_AlphanumericAscii) set_failed_rule :_AlphanumericAscii unless _tmp return _tmp end # BOM = %literals.BOM def _BOM _tmp = @_grammar_literals.external_invoke(self, :_BOM) set_failed_rule :_BOM unless _tmp return _tmp end # Newline = %literals.Newline def _Newline _tmp = @_grammar_literals.external_invoke(self, :_Newline) set_failed_rule :_Newline unless _tmp return _tmp end # NonAlphanumeric = %literals.NonAlphanumeric def _NonAlphanumeric _tmp = @_grammar_literals.external_invoke(self, :_NonAlphanumeric) set_failed_rule :_NonAlphanumeric unless _tmp return _tmp end # Spacechar = %literals.Spacechar def _Spacechar _tmp = @_grammar_literals.external_invoke(self, :_Spacechar) set_failed_rule :_Spacechar unless _tmp return _tmp end # HexEntity = "&" "#" /[Xx]/ < /[0-9a-fA-F]+/ > ";" { [text.to_i(16)].pack 'U' } def _HexEntity _save = self.pos while true # sequence _tmp = match_string("&") unless _tmp self.pos = _save break end _tmp = match_string("#") unless _tmp self.pos = _save break end _tmp = scan(/\A(?-mix:[Xx])/) unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[0-9a-fA-F]+)/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(";") unless _tmp self.pos = _save break end @result = begin; [text.to_i(16)].pack 'U' ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_HexEntity unless _tmp return _tmp end # DecEntity = "&" "#" < /[0-9]+/ > ";" { [text.to_i].pack 'U' } def _DecEntity _save = self.pos while true # sequence _tmp = match_string("&") unless _tmp self.pos = _save break end _tmp = match_string("#") unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[0-9]+)/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(";") unless _tmp self.pos = _save break end @result = begin; [text.to_i].pack 'U' ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DecEntity unless _tmp return _tmp end # CharEntity = "&" < /[A-Za-z0-9]+/ > ";" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else "&#{text};" end } def _CharEntity _save = self.pos while true # sequence _tmp = match_string("&") unless _tmp self.pos = _save break end _text_start = self.pos _tmp = scan(/\A(?-mix:[A-Za-z0-9]+)/) if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string(";") unless _tmp self.pos = _save break end @result = begin; if entity = HTML_ENTITIES[text] then entity.pack 'U*' else "&#{text};" end ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_CharEntity unless _tmp return _tmp end # NonindentSpace = (" " | " " | " " | "") def _NonindentSpace _save = self.pos while true # choice _tmp = match_string(" ") break if _tmp self.pos = _save _tmp = match_string(" ") break if _tmp self.pos = _save _tmp = match_string(" ") break if _tmp self.pos = _save _tmp = match_string("") break if _tmp self.pos = _save break end # end choice set_failed_rule :_NonindentSpace unless _tmp return _tmp end # Indent = ("\t" | " ") def _Indent _save = self.pos while true # choice _tmp = match_string("\t") break if _tmp self.pos = _save _tmp = match_string(" ") break if _tmp self.pos = _save break end # end choice set_failed_rule :_Indent unless _tmp return _tmp end # IndentedLine = Indent Line def _IndentedLine _save = self.pos while true # sequence _tmp = apply(:_Indent) unless _tmp self.pos = _save break end _tmp = apply(:_Line) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_IndentedLine unless _tmp return _tmp end # OptionallyIndentedLine = Indent? Line def _OptionallyIndentedLine _save = self.pos while true # sequence _save1 = self.pos _tmp = apply(:_Indent) unless _tmp _tmp = true self.pos = _save1 end unless _tmp self.pos = _save break end _tmp = apply(:_Line) unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_OptionallyIndentedLine unless _tmp return _tmp end # StartList = &. { [] } def _StartList _save = self.pos while true # sequence _save1 = self.pos _tmp = get_byte self.pos = _save1 unless _tmp self.pos = _save break end @result = begin; [] ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_StartList unless _tmp return _tmp end # Line = RawLine:a { a } def _Line _save = self.pos while true # sequence _tmp = apply(:_RawLine) a = @result unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Line unless _tmp return _tmp end # RawLine = (< (!"\r" !"\n" .)* Newline > | < .+ > Eof) { text } def _RawLine _save = self.pos while true # sequence _save1 = self.pos while true # choice _text_start = self.pos _save2 = self.pos while true # sequence while true _save4 = self.pos while true # sequence _save5 = self.pos _tmp = match_string("\r") _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _save6 = self.pos _tmp = match_string("\n") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save4 break end _tmp = get_byte unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save2 break end _tmp = apply(:_Newline) unless _tmp self.pos = _save2 end break end # end sequence if _tmp text = get_text(_text_start) end break if _tmp self.pos = _save1 _save7 = self.pos while true # sequence _text_start = self.pos _save8 = self.pos _tmp = get_byte if _tmp while true _tmp = get_byte break unless _tmp end _tmp = true else self.pos = _save8 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save7 break end _tmp = apply(:_Eof) unless _tmp self.pos = _save7 end break end # end sequence break if _tmp self.pos = _save1 break end # end choice unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawLine unless _tmp return _tmp end # SkipBlock = (HtmlBlock | (!"#" !SetextBottom1 !SetextBottom2 !BlankLine RawLine)+ BlankLine* | BlankLine+ | RawLine) def _SkipBlock _save = self.pos while true # choice _tmp = apply(:_HtmlBlock) break if _tmp self.pos = _save _save1 = self.pos while true # sequence _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = match_string("#") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _save5 = self.pos _tmp = apply(:_SetextBottom1) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save3 break end _save6 = self.pos _tmp = apply(:_SetextBottom2) _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save3 break end _save7 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save3 break end _tmp = apply(:_RawLine) unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save8 = self.pos while true # sequence _save9 = self.pos _tmp = match_string("#") _tmp = _tmp ? nil : true self.pos = _save9 unless _tmp self.pos = _save8 break end _save10 = self.pos _tmp = apply(:_SetextBottom1) _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save8 break end _save11 = self.pos _tmp = apply(:_SetextBottom2) _tmp = _tmp ? nil : true self.pos = _save11 unless _tmp self.pos = _save8 break end _save12 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save12 unless _tmp self.pos = _save8 break end _tmp = apply(:_RawLine) unless _tmp self.pos = _save8 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save1 break end while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true unless _tmp self.pos = _save1 end break end # end sequence break if _tmp self.pos = _save _save14 = self.pos _tmp = apply(:_BlankLine) if _tmp while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true else self.pos = _save14 end break if _tmp self.pos = _save _tmp = apply(:_RawLine) break if _tmp self.pos = _save break end # end choice set_failed_rule :_SkipBlock unless _tmp return _tmp end # ExtendedSpecialChar = &{ notes? } "^" def _ExtendedSpecialChar _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("^") unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_ExtendedSpecialChar unless _tmp return _tmp end # NoteReference = &{ notes? } RawNoteReference:ref { note_for ref } def _NoteReference _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_RawNoteReference) ref = @result unless _tmp self.pos = _save break end @result = begin; note_for ref ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_NoteReference unless _tmp return _tmp end # RawNoteReference = "[^" < (!Newline !"]" .)+ > "]" { text } def _RawNoteReference _save = self.pos while true # sequence _tmp = match_string("[^") unless _tmp self.pos = _save break end _text_start = self.pos _save1 = self.pos _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _save4 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save2 break end _tmp = get_byte unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save5 = self.pos while true # sequence _save6 = self.pos _tmp = apply(:_Newline) _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save5 break end _save7 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save7 unless _tmp self.pos = _save5 break end _tmp = get_byte unless _tmp self.pos = _save5 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = match_string("]") unless _tmp self.pos = _save break end @result = begin; text ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawNoteReference unless _tmp return _tmp end # Note = &{ notes? } NonindentSpace RawNoteReference:ref ":" Sp StartList:a RawNoteBlock (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil } def _Note _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_NonindentSpace) unless _tmp self.pos = _save break end _tmp = apply(:_RawNoteReference) ref = @result unless _tmp self.pos = _save break end _tmp = match_string(":") unless _tmp self.pos = _save break end _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _tmp = apply(:_RawNoteBlock) unless _tmp self.pos = _save break end while true _save3 = self.pos while true # sequence _save4 = self.pos _tmp = apply(:_Indent) self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_RawNoteBlock) i = @result unless _tmp self.pos = _save3 break end @result = begin; a.concat i ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; @footnotes[ref] = paragraph a nil ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_Note unless _tmp return _tmp end # InlineNote = &{ notes? } "^[" StartList:a (!"]" Inline:l { a << l })+ "]" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref } def _InlineNote _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; notes? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = match_string("^[") unless _tmp self.pos = _save break end _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _save4 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save4 unless _tmp self.pos = _save3 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save3 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save3 end break end # end sequence if _tmp while true _save5 = self.pos while true # sequence _save6 = self.pos _tmp = match_string("]") _tmp = _tmp ? nil : true self.pos = _save6 unless _tmp self.pos = _save5 break end _tmp = apply(:_Inline) l = @result unless _tmp self.pos = _save5 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save5 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save2 end unless _tmp self.pos = _save break end _tmp = match_string("]") unless _tmp self.pos = _save break end @result = begin; ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_InlineNote unless _tmp return _tmp end # Notes = (Note | SkipBlock)* def _Notes while true _save1 = self.pos while true # choice _tmp = apply(:_Note) break if _tmp self.pos = _save1 _tmp = apply(:_SkipBlock) break if _tmp self.pos = _save1 break end # end choice break unless _tmp end _tmp = true set_failed_rule :_Notes unless _tmp return _tmp end # RawNoteBlock = StartList:a (!BlankLine OptionallyIndentedLine:l { a << l })+ < BlankLine* > { a << text } { a } def _RawNoteBlock _save = self.pos while true # sequence _tmp = apply(:_StartList) a = @result unless _tmp self.pos = _save break end _save1 = self.pos _save2 = self.pos while true # sequence _save3 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save3 unless _tmp self.pos = _save2 break end _tmp = apply(:_OptionallyIndentedLine) l = @result unless _tmp self.pos = _save2 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save2 end break end # end sequence if _tmp while true _save4 = self.pos while true # sequence _save5 = self.pos _tmp = apply(:_BlankLine) _tmp = _tmp ? nil : true self.pos = _save5 unless _tmp self.pos = _save4 break end _tmp = apply(:_OptionallyIndentedLine) l = @result unless _tmp self.pos = _save4 break end @result = begin; a << l ; end _tmp = true unless _tmp self.pos = _save4 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end _text_start = self.pos while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end @result = begin; a << text ; end _tmp = true unless _tmp self.pos = _save break end @result = begin; a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_RawNoteBlock unless _tmp return _tmp end # CodeFence = &{ github? } Ticks3 (Sp StrChunk:format)? Spnl < ((!"`" Nonspacechar)+ | !Ticks3 "`"+ | Spacechar | Newline)+ > Ticks3 Sp Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim } def _CodeFence _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; github? ; end self.pos = _save1 unless _tmp self.pos = _save break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save break end _save2 = self.pos _save3 = self.pos while true # sequence _tmp = apply(:_Sp) unless _tmp self.pos = _save3 break end _tmp = apply(:_StrChunk) format = @result unless _tmp self.pos = _save3 end break end # end sequence unless _tmp _tmp = true self.pos = _save2 end unless _tmp self.pos = _save break end _tmp = apply(:_Spnl) unless _tmp self.pos = _save break end _text_start = self.pos _save4 = self.pos _save5 = self.pos while true # choice _save6 = self.pos _save7 = self.pos while true # sequence _save8 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save8 unless _tmp self.pos = _save7 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save7 end break end # end sequence if _tmp while true _save9 = self.pos while true # sequence _save10 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save10 unless _tmp self.pos = _save9 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save9 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save6 end break if _tmp self.pos = _save5 _save11 = self.pos while true # sequence _save12 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save12 unless _tmp self.pos = _save11 break end _save13 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save13 end unless _tmp self.pos = _save11 end break end # end sequence break if _tmp self.pos = _save5 _tmp = apply(:_Spacechar) break if _tmp self.pos = _save5 _tmp = apply(:_Newline) break if _tmp self.pos = _save5 break end # end choice if _tmp while true _save14 = self.pos while true # choice _save15 = self.pos _save16 = self.pos while true # sequence _save17 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save17 unless _tmp self.pos = _save16 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save16 end break end # end sequence if _tmp while true _save18 = self.pos while true # sequence _save19 = self.pos _tmp = match_string("`") _tmp = _tmp ? nil : true self.pos = _save19 unless _tmp self.pos = _save18 break end _tmp = apply(:_Nonspacechar) unless _tmp self.pos = _save18 end break end # end sequence break unless _tmp end _tmp = true else self.pos = _save15 end break if _tmp self.pos = _save14 _save20 = self.pos while true # sequence _save21 = self.pos _tmp = apply(:_Ticks3) _tmp = _tmp ? nil : true self.pos = _save21 unless _tmp self.pos = _save20 break end _save22 = self.pos _tmp = match_string("`") if _tmp while true _tmp = match_string("`") break unless _tmp end _tmp = true else self.pos = _save22 end unless _tmp self.pos = _save20 end break end # end sequence break if _tmp self.pos = _save14 _tmp = apply(:_Spacechar) break if _tmp self.pos = _save14 _tmp = apply(:_Newline) break if _tmp self.pos = _save14 break end # end choice break unless _tmp end _tmp = true else self.pos = _save4 end if _tmp text = get_text(_text_start) end unless _tmp self.pos = _save break end _tmp = apply(:_Ticks3) unless _tmp self.pos = _save break end _tmp = apply(:_Sp) unless _tmp self.pos = _save break end while true _tmp = apply(:_Newline) break unless _tmp end _tmp = true unless _tmp self.pos = _save break end @result = begin; verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_CodeFence unless _tmp return _tmp end # DefinitionList = &{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten } def _DefinitionList _save = self.pos while true # sequence _save1 = self.pos _tmp = begin; definition_lists? ; end self.pos = _save1 unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_DefinitionListItem) if _tmp _ary << @result while true _tmp = apply(:_DefinitionListItem) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end list = @result unless _tmp self.pos = _save break end @result = begin; RDoc::Markup::List.new :NOTE, *list.flatten ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionList unless _tmp return _tmp end # DefinitionListItem = DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items } def _DefinitionListItem _save = self.pos while true # sequence _save1 = self.pos _ary = [] _tmp = apply(:_DefinitionListLabel) if _tmp _ary << @result while true _tmp = apply(:_DefinitionListLabel) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save1 end label = @result unless _tmp self.pos = _save break end _save2 = self.pos _ary = [] _tmp = apply(:_DefinitionListDefinition) if _tmp _ary << @result while true _tmp = apply(:_DefinitionListDefinition) _ary << @result if _tmp break unless _tmp end _tmp = true @result = _ary else self.pos = _save2 end defns = @result unless _tmp self.pos = _save break end @result = begin; list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionListItem unless _tmp return _tmp end # DefinitionListLabel = StrChunk:label Sp Newline { label } def _DefinitionListLabel _save = self.pos while true # sequence _tmp = apply(:_StrChunk) label = @result unless _tmp self.pos = _save break end _tmp = apply(:_Sp) unless _tmp self.pos = _save break end _tmp = apply(:_Newline) unless _tmp self.pos = _save break end @result = begin; label ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionListLabel unless _tmp return _tmp end # DefinitionListDefinition = NonindentSpace ":" Space Inlines:a BlankLine+ { paragraph a } def _DefinitionListDefinition _save = self.pos while true # sequence _tmp = apply(:_NonindentSpace) unless _tmp self.pos = _save break end _tmp = match_string(":") unless _tmp self.pos = _save break end _tmp = apply(:_Space) unless _tmp self.pos = _save break end _tmp = apply(:_Inlines) a = @result unless _tmp self.pos = _save break end _save1 = self.pos _tmp = apply(:_BlankLine) if _tmp while true _tmp = apply(:_BlankLine) break unless _tmp end _tmp = true else self.pos = _save1 end unless _tmp self.pos = _save break end @result = begin; paragraph a ; end _tmp = true unless _tmp self.pos = _save end break end # end sequence set_failed_rule :_DefinitionListDefinition unless _tmp return _tmp end Rules = {} Rules[:_root] = rule_info("root", "Doc") Rules[:_Doc] = rule_info("Doc", "BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) }") Rules[:_Block] = rule_info("Block", "BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)") Rules[:_Para] = rule_info("Para", "NonindentSpace Inlines:a BlankLine+ { paragraph a }") Rules[:_Plain] = rule_info("Plain", "Inlines:a { paragraph a }") Rules[:_AtxInline] = rule_info("AtxInline", "!Newline !(Sp? \"\#\"* Sp Newline) Inline") Rules[:_AtxStart] = rule_info("AtxStart", "< (\"\#\#\#\#\#\#\" | \"\#\#\#\#\#\" | \"\#\#\#\#\" | \"\#\#\#\" | \"\#\#\" | \"\#\") > { text.length }") Rules[:_AtxHeading] = rule_info("AtxHeading", "AtxStart:s Sp? AtxInline+:a (Sp? \"\#\"* Sp)? Newline { RDoc::Markup::Heading.new(s, a.join) }") Rules[:_SetextHeading] = rule_info("SetextHeading", "(SetextHeading1 | SetextHeading2)") Rules[:_SetextBottom1] = rule_info("SetextBottom1", "\"===\" \"=\"* Newline") Rules[:_SetextBottom2] = rule_info("SetextBottom2", "\"---\" \"-\"* Newline") Rules[:_SetextHeading1] = rule_info("SetextHeading1", "&(RawLine SetextBottom1) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom1 { RDoc::Markup::Heading.new(1, a.join) }") Rules[:_SetextHeading2] = rule_info("SetextHeading2", "&(RawLine SetextBottom2) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) }") Rules[:_Heading] = rule_info("Heading", "(SetextHeading | AtxHeading)") Rules[:_BlockQuote] = rule_info("BlockQuote", "BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) }") Rules[:_BlockQuoteRaw] = rule_info("BlockQuoteRaw", "StartList:a (\">\" \" \"? Line:l { a << l } (!\">\" !BlankLine Line:c { a << c })* (BlankLine:n { a << n })*)+ { inner_parse a.join }") Rules[:_NonblankIndentedLine] = rule_info("NonblankIndentedLine", "!BlankLine IndentedLine") Rules[:_VerbatimChunk] = rule_info("VerbatimChunk", "BlankLine*:a NonblankIndentedLine+:b { a.concat b }") Rules[:_Verbatim] = rule_info("Verbatim", "VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) }") Rules[:_HorizontalRule] = rule_info("HorizontalRule", "NonindentSpace (\"*\" Sp \"*\" Sp \"*\" (Sp \"*\")* | \"-\" Sp \"-\" Sp \"-\" (Sp \"-\")* | \"_\" Sp \"_\" Sp \"_\" (Sp \"_\")*) Sp Newline BlankLine+ { RDoc::Markup::Rule.new 1 }") Rules[:_Bullet] = rule_info("Bullet", "!HorizontalRule NonindentSpace (\"+\" | \"*\" | \"-\") Spacechar+") Rules[:_BulletList] = rule_info("BulletList", "&Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) }") Rules[:_ListTight] = rule_info("ListTight", "ListItemTight+:a BlankLine* !(Bullet | Enumerator) { a }") Rules[:_ListLoose] = rule_info("ListLoose", "StartList:a (ListItem:b BlankLine* { a << b })+ { a }") Rules[:_ListItem] = rule_info("ListItem", "(Bullet | Enumerator) StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a }") Rules[:_ListItemTight] = rule_info("ListItemTight", "(Bullet | Enumerator) ListBlock:a (!BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a }") Rules[:_ListBlock] = rule_info("ListBlock", "!BlankLine Line:a ListBlockLine*:c { [a, *c] }") Rules[:_ListContinuationBlock] = rule_info("ListContinuationBlock", "StartList:a BlankLine* { a << \"\\n\" } (Indent ListBlock:b { a.concat b })+ { a }") Rules[:_Enumerator] = rule_info("Enumerator", "NonindentSpace [0-9]+ \".\" Spacechar+") Rules[:_OrderedList] = rule_info("OrderedList", "&Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) }") Rules[:_ListBlockLine] = rule_info("ListBlockLine", "!BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine") Rules[:_HtmlBlockOpenAddress] = rule_info("HtmlBlockOpenAddress", "\"<\" Spnl (\"address\" | \"ADDRESS\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseAddress] = rule_info("HtmlBlockCloseAddress", "\"<\" Spnl \"/\" (\"address\" | \"ADDRESS\") Spnl \">\"") Rules[:_HtmlBlockAddress] = rule_info("HtmlBlockAddress", "HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress") Rules[:_HtmlBlockOpenBlockquote] = rule_info("HtmlBlockOpenBlockquote", "\"<\" Spnl (\"blockquote\" | \"BLOCKQUOTE\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseBlockquote] = rule_info("HtmlBlockCloseBlockquote", "\"<\" Spnl \"/\" (\"blockquote\" | \"BLOCKQUOTE\") Spnl \">\"") Rules[:_HtmlBlockBlockquote] = rule_info("HtmlBlockBlockquote", "HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote") Rules[:_HtmlBlockOpenCenter] = rule_info("HtmlBlockOpenCenter", "\"<\" Spnl (\"center\" | \"CENTER\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseCenter] = rule_info("HtmlBlockCloseCenter", "\"<\" Spnl \"/\" (\"center\" | \"CENTER\") Spnl \">\"") Rules[:_HtmlBlockCenter] = rule_info("HtmlBlockCenter", "HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter") Rules[:_HtmlBlockOpenDir] = rule_info("HtmlBlockOpenDir", "\"<\" Spnl (\"dir\" | \"DIR\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDir] = rule_info("HtmlBlockCloseDir", "\"<\" Spnl \"/\" (\"dir\" | \"DIR\") Spnl \">\"") Rules[:_HtmlBlockDir] = rule_info("HtmlBlockDir", "HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir") Rules[:_HtmlBlockOpenDiv] = rule_info("HtmlBlockOpenDiv", "\"<\" Spnl (\"div\" | \"DIV\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDiv] = rule_info("HtmlBlockCloseDiv", "\"<\" Spnl \"/\" (\"div\" | \"DIV\") Spnl \">\"") Rules[:_HtmlBlockDiv] = rule_info("HtmlBlockDiv", "HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv") Rules[:_HtmlBlockOpenDl] = rule_info("HtmlBlockOpenDl", "\"<\" Spnl (\"dl\" | \"DL\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDl] = rule_info("HtmlBlockCloseDl", "\"<\" Spnl \"/\" (\"dl\" | \"DL\") Spnl \">\"") Rules[:_HtmlBlockDl] = rule_info("HtmlBlockDl", "HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl") Rules[:_HtmlBlockOpenFieldset] = rule_info("HtmlBlockOpenFieldset", "\"<\" Spnl (\"fieldset\" | \"FIELDSET\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseFieldset] = rule_info("HtmlBlockCloseFieldset", "\"<\" Spnl \"/\" (\"fieldset\" | \"FIELDSET\") Spnl \">\"") Rules[:_HtmlBlockFieldset] = rule_info("HtmlBlockFieldset", "HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset") Rules[:_HtmlBlockOpenForm] = rule_info("HtmlBlockOpenForm", "\"<\" Spnl (\"form\" | \"FORM\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseForm] = rule_info("HtmlBlockCloseForm", "\"<\" Spnl \"/\" (\"form\" | \"FORM\") Spnl \">\"") Rules[:_HtmlBlockForm] = rule_info("HtmlBlockForm", "HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm") Rules[:_HtmlBlockOpenH1] = rule_info("HtmlBlockOpenH1", "\"<\" Spnl (\"h1\" | \"H1\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH1] = rule_info("HtmlBlockCloseH1", "\"<\" Spnl \"/\" (\"h1\" | \"H1\") Spnl \">\"") Rules[:_HtmlBlockH1] = rule_info("HtmlBlockH1", "HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1") Rules[:_HtmlBlockOpenH2] = rule_info("HtmlBlockOpenH2", "\"<\" Spnl (\"h2\" | \"H2\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH2] = rule_info("HtmlBlockCloseH2", "\"<\" Spnl \"/\" (\"h2\" | \"H2\") Spnl \">\"") Rules[:_HtmlBlockH2] = rule_info("HtmlBlockH2", "HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2") Rules[:_HtmlBlockOpenH3] = rule_info("HtmlBlockOpenH3", "\"<\" Spnl (\"h3\" | \"H3\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH3] = rule_info("HtmlBlockCloseH3", "\"<\" Spnl \"/\" (\"h3\" | \"H3\") Spnl \">\"") Rules[:_HtmlBlockH3] = rule_info("HtmlBlockH3", "HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3") Rules[:_HtmlBlockOpenH4] = rule_info("HtmlBlockOpenH4", "\"<\" Spnl (\"h4\" | \"H4\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH4] = rule_info("HtmlBlockCloseH4", "\"<\" Spnl \"/\" (\"h4\" | \"H4\") Spnl \">\"") Rules[:_HtmlBlockH4] = rule_info("HtmlBlockH4", "HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4") Rules[:_HtmlBlockOpenH5] = rule_info("HtmlBlockOpenH5", "\"<\" Spnl (\"h5\" | \"H5\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH5] = rule_info("HtmlBlockCloseH5", "\"<\" Spnl \"/\" (\"h5\" | \"H5\") Spnl \">\"") Rules[:_HtmlBlockH5] = rule_info("HtmlBlockH5", "HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5") Rules[:_HtmlBlockOpenH6] = rule_info("HtmlBlockOpenH6", "\"<\" Spnl (\"h6\" | \"H6\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseH6] = rule_info("HtmlBlockCloseH6", "\"<\" Spnl \"/\" (\"h6\" | \"H6\") Spnl \">\"") Rules[:_HtmlBlockH6] = rule_info("HtmlBlockH6", "HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6") Rules[:_HtmlBlockOpenMenu] = rule_info("HtmlBlockOpenMenu", "\"<\" Spnl (\"menu\" | \"MENU\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseMenu] = rule_info("HtmlBlockCloseMenu", "\"<\" Spnl \"/\" (\"menu\" | \"MENU\") Spnl \">\"") Rules[:_HtmlBlockMenu] = rule_info("HtmlBlockMenu", "HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu") Rules[:_HtmlBlockOpenNoframes] = rule_info("HtmlBlockOpenNoframes", "\"<\" Spnl (\"noframes\" | \"NOFRAMES\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseNoframes] = rule_info("HtmlBlockCloseNoframes", "\"<\" Spnl \"/\" (\"noframes\" | \"NOFRAMES\") Spnl \">\"") Rules[:_HtmlBlockNoframes] = rule_info("HtmlBlockNoframes", "HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes") Rules[:_HtmlBlockOpenNoscript] = rule_info("HtmlBlockOpenNoscript", "\"<\" Spnl (\"noscript\" | \"NOSCRIPT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseNoscript] = rule_info("HtmlBlockCloseNoscript", "\"<\" Spnl \"/\" (\"noscript\" | \"NOSCRIPT\") Spnl \">\"") Rules[:_HtmlBlockNoscript] = rule_info("HtmlBlockNoscript", "HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript") Rules[:_HtmlBlockOpenOl] = rule_info("HtmlBlockOpenOl", "\"<\" Spnl (\"ol\" | \"OL\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseOl] = rule_info("HtmlBlockCloseOl", "\"<\" Spnl \"/\" (\"ol\" | \"OL\") Spnl \">\"") Rules[:_HtmlBlockOl] = rule_info("HtmlBlockOl", "HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl") Rules[:_HtmlBlockOpenP] = rule_info("HtmlBlockOpenP", "\"<\" Spnl (\"p\" | \"P\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseP] = rule_info("HtmlBlockCloseP", "\"<\" Spnl \"/\" (\"p\" | \"P\") Spnl \">\"") Rules[:_HtmlBlockP] = rule_info("HtmlBlockP", "HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP") Rules[:_HtmlBlockOpenPre] = rule_info("HtmlBlockOpenPre", "\"<\" Spnl (\"pre\" | \"PRE\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockClosePre] = rule_info("HtmlBlockClosePre", "\"<\" Spnl \"/\" (\"pre\" | \"PRE\") Spnl \">\"") Rules[:_HtmlBlockPre] = rule_info("HtmlBlockPre", "HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre") Rules[:_HtmlBlockOpenTable] = rule_info("HtmlBlockOpenTable", "\"<\" Spnl (\"table\" | \"TABLE\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTable] = rule_info("HtmlBlockCloseTable", "\"<\" Spnl \"/\" (\"table\" | \"TABLE\") Spnl \">\"") Rules[:_HtmlBlockTable] = rule_info("HtmlBlockTable", "HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable") Rules[:_HtmlBlockOpenUl] = rule_info("HtmlBlockOpenUl", "\"<\" Spnl (\"ul\" | \"UL\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseUl] = rule_info("HtmlBlockCloseUl", "\"<\" Spnl \"/\" (\"ul\" | \"UL\") Spnl \">\"") Rules[:_HtmlBlockUl] = rule_info("HtmlBlockUl", "HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl") Rules[:_HtmlBlockOpenDd] = rule_info("HtmlBlockOpenDd", "\"<\" Spnl (\"dd\" | \"DD\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDd] = rule_info("HtmlBlockCloseDd", "\"<\" Spnl \"/\" (\"dd\" | \"DD\") Spnl \">\"") Rules[:_HtmlBlockDd] = rule_info("HtmlBlockDd", "HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd") Rules[:_HtmlBlockOpenDt] = rule_info("HtmlBlockOpenDt", "\"<\" Spnl (\"dt\" | \"DT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseDt] = rule_info("HtmlBlockCloseDt", "\"<\" Spnl \"/\" (\"dt\" | \"DT\") Spnl \">\"") Rules[:_HtmlBlockDt] = rule_info("HtmlBlockDt", "HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt") Rules[:_HtmlBlockOpenFrameset] = rule_info("HtmlBlockOpenFrameset", "\"<\" Spnl (\"frameset\" | \"FRAMESET\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseFrameset] = rule_info("HtmlBlockCloseFrameset", "\"<\" Spnl \"/\" (\"frameset\" | \"FRAMESET\") Spnl \">\"") Rules[:_HtmlBlockFrameset] = rule_info("HtmlBlockFrameset", "HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset") Rules[:_HtmlBlockOpenLi] = rule_info("HtmlBlockOpenLi", "\"<\" Spnl (\"li\" | \"LI\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseLi] = rule_info("HtmlBlockCloseLi", "\"<\" Spnl \"/\" (\"li\" | \"LI\") Spnl \">\"") Rules[:_HtmlBlockLi] = rule_info("HtmlBlockLi", "HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi") Rules[:_HtmlBlockOpenTbody] = rule_info("HtmlBlockOpenTbody", "\"<\" Spnl (\"tbody\" | \"TBODY\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTbody] = rule_info("HtmlBlockCloseTbody", "\"<\" Spnl \"/\" (\"tbody\" | \"TBODY\") Spnl \">\"") Rules[:_HtmlBlockTbody] = rule_info("HtmlBlockTbody", "HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody") Rules[:_HtmlBlockOpenTd] = rule_info("HtmlBlockOpenTd", "\"<\" Spnl (\"td\" | \"TD\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTd] = rule_info("HtmlBlockCloseTd", "\"<\" Spnl \"/\" (\"td\" | \"TD\") Spnl \">\"") Rules[:_HtmlBlockTd] = rule_info("HtmlBlockTd", "HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd") Rules[:_HtmlBlockOpenTfoot] = rule_info("HtmlBlockOpenTfoot", "\"<\" Spnl (\"tfoot\" | \"TFOOT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTfoot] = rule_info("HtmlBlockCloseTfoot", "\"<\" Spnl \"/\" (\"tfoot\" | \"TFOOT\") Spnl \">\"") Rules[:_HtmlBlockTfoot] = rule_info("HtmlBlockTfoot", "HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot") Rules[:_HtmlBlockOpenTh] = rule_info("HtmlBlockOpenTh", "\"<\" Spnl (\"th\" | \"TH\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTh] = rule_info("HtmlBlockCloseTh", "\"<\" Spnl \"/\" (\"th\" | \"TH\") Spnl \">\"") Rules[:_HtmlBlockTh] = rule_info("HtmlBlockTh", "HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh") Rules[:_HtmlBlockOpenThead] = rule_info("HtmlBlockOpenThead", "\"<\" Spnl (\"thead\" | \"THEAD\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseThead] = rule_info("HtmlBlockCloseThead", "\"<\" Spnl \"/\" (\"thead\" | \"THEAD\") Spnl \">\"") Rules[:_HtmlBlockThead] = rule_info("HtmlBlockThead", "HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead") Rules[:_HtmlBlockOpenTr] = rule_info("HtmlBlockOpenTr", "\"<\" Spnl (\"tr\" | \"TR\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseTr] = rule_info("HtmlBlockCloseTr", "\"<\" Spnl \"/\" (\"tr\" | \"TR\") Spnl \">\"") Rules[:_HtmlBlockTr] = rule_info("HtmlBlockTr", "HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr") Rules[:_HtmlBlockOpenScript] = rule_info("HtmlBlockOpenScript", "\"<\" Spnl (\"script\" | \"SCRIPT\") Spnl HtmlAttribute* \">\"") Rules[:_HtmlBlockCloseScript] = rule_info("HtmlBlockCloseScript", "\"<\" Spnl \"/\" (\"script\" | \"SCRIPT\") Spnl \">\"") Rules[:_HtmlBlockScript] = rule_info("HtmlBlockScript", "HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript") Rules[:_HtmlBlockInTags] = rule_info("HtmlBlockInTags", "(HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript)") Rules[:_HtmlBlock] = rule_info("HtmlBlock", "< (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > BlankLine+ { if html? then RDoc::Markup::Raw.new text end }") Rules[:_HtmlUnclosed] = rule_info("HtmlUnclosed", "\"<\" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl \">\"") Rules[:_HtmlUnclosedType] = rule_info("HtmlUnclosedType", "(\"HR\" | \"hr\")") Rules[:_HtmlBlockSelfClosing] = rule_info("HtmlBlockSelfClosing", "\"<\" Spnl HtmlBlockType Spnl HtmlAttribute* \"/\" Spnl \">\"") Rules[:_HtmlBlockType] = rule_info("HtmlBlockType", "(\"ADDRESS\" | \"BLOCKQUOTE\" | \"CENTER\" | \"DD\" | \"DIR\" | \"DIV\" | \"DL\" | \"DT\" | \"FIELDSET\" | \"FORM\" | \"FRAMESET\" | \"H1\" | \"H2\" | \"H3\" | \"H4\" | \"H5\" | \"H6\" | \"HR\" | \"ISINDEX\" | \"LI\" | \"MENU\" | \"NOFRAMES\" | \"NOSCRIPT\" | \"OL\" | \"P\" | \"PRE\" | \"SCRIPT\" | \"TABLE\" | \"TBODY\" | \"TD\" | \"TFOOT\" | \"TH\" | \"THEAD\" | \"TR\" | \"UL\" | \"address\" | \"blockquote\" | \"center\" | \"dd\" | \"dir\" | \"div\" | \"dl\" | \"dt\" | \"fieldset\" | \"form\" | \"frameset\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"hr\" | \"isindex\" | \"li\" | \"menu\" | \"noframes\" | \"noscript\" | \"ol\" | \"p\" | \"pre\" | \"script\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"ul\")") Rules[:_StyleOpen] = rule_info("StyleOpen", "\"<\" Spnl (\"style\" | \"STYLE\") Spnl HtmlAttribute* \">\"") Rules[:_StyleClose] = rule_info("StyleClose", "\"<\" Spnl \"/\" (\"style\" | \"STYLE\") Spnl \">\"") Rules[:_InStyleTags] = rule_info("InStyleTags", "StyleOpen (!StyleClose .)* StyleClose") Rules[:_StyleBlock] = rule_info("StyleBlock", "< InStyleTags > BlankLine* { if css? then RDoc::Markup::Raw.new text end }") Rules[:_Inlines] = rule_info("Inlines", "(!Endline Inline:i { i } | Endline:c &Inline { c })+:chunks Endline? { chunks }") Rules[:_Inline] = rule_info("Inline", "(Str | Endline | UlOrStarLine | Space | Strong | Emph | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol)") Rules[:_Space] = rule_info("Space", "Spacechar+ { \" \" }") Rules[:_Str] = rule_info("Str", "StartList:a < NormalChar+ > { a = text } (StrChunk:c { a << c })* { a }") Rules[:_StrChunk] = rule_info("StrChunk", "< (NormalChar | \"_\"+ &Alphanumeric)+ > { text }") Rules[:_EscapedChar] = rule_info("EscapedChar", "\"\\\\\" !Newline < /[:\\\\`|*_{}\\[\\]()\#+.!><-]/ > { text }") Rules[:_Entity] = rule_info("Entity", "(HexEntity | DecEntity | CharEntity):a { a }") Rules[:_Endline] = rule_info("Endline", "(LineBreak | TerminalEndline | NormalEndline)") Rules[:_NormalEndline] = rule_info("NormalEndline", "Sp Newline !BlankLine !\">\" !AtxStart !(Line (\"===\" \"=\"* | \"---\" \"-\"*) Newline) { \"\\n\" }") Rules[:_TerminalEndline] = rule_info("TerminalEndline", "Sp Newline Eof") Rules[:_LineBreak] = rule_info("LineBreak", "\" \" NormalEndline { RDoc::Markup::HardBreak.new }") Rules[:_Symbol] = rule_info("Symbol", "< SpecialChar > { text }") Rules[:_UlOrStarLine] = rule_info("UlOrStarLine", "(UlLine | StarLine):a { a }") Rules[:_StarLine] = rule_info("StarLine", "(< \"****\" \"*\"* > { text } | < Spacechar \"*\"+ &Spacechar > { text })") Rules[:_UlLine] = rule_info("UlLine", "(< \"____\" \"_\"* > { text } | < Spacechar \"_\"+ &Spacechar > { text })") Rules[:_Emph] = rule_info("Emph", "(EmphStar | EmphUl)") Rules[:_OneStarOpen] = rule_info("OneStarOpen", "!StarLine \"*\" !Spacechar !Newline") Rules[:_OneStarClose] = rule_info("OneStarClose", "!Spacechar !Newline Inline:a \"*\" { a }") Rules[:_EmphStar] = rule_info("EmphStar", "OneStarOpen StartList:a (!OneStarClose Inline:l { a << l })* OneStarClose:l { a << l } { emphasis a.join }") Rules[:_OneUlOpen] = rule_info("OneUlOpen", "!UlLine \"_\" !Spacechar !Newline") Rules[:_OneUlClose] = rule_info("OneUlClose", "!Spacechar !Newline Inline:a \"_\" { a }") Rules[:_EmphUl] = rule_info("EmphUl", "OneUlOpen StartList:a (!OneUlClose Inline:l { a << l })* OneUlClose:l { a << l } { emphasis a.join }") Rules[:_Strong] = rule_info("Strong", "(StrongStar | StrongUl)") Rules[:_TwoStarOpen] = rule_info("TwoStarOpen", "!StarLine \"**\" !Spacechar !Newline") Rules[:_TwoStarClose] = rule_info("TwoStarClose", "!Spacechar !Newline Inline:a \"**\" { a }") Rules[:_StrongStar] = rule_info("StrongStar", "TwoStarOpen StartList:a (!TwoStarClose Inline:l { a << l })* TwoStarClose:l { a << l } { strong a.join }") Rules[:_TwoUlOpen] = rule_info("TwoUlOpen", "!UlLine \"__\" !Spacechar !Newline") Rules[:_TwoUlClose] = rule_info("TwoUlClose", "!Spacechar !Newline Inline:a \"__\" { a }") Rules[:_StrongUl] = rule_info("StrongUl", "TwoUlOpen StartList:a (!TwoUlClose Inline:i { a << i })* TwoUlClose:l { a << l } { strong a.join }") Rules[:_Image] = rule_info("Image", "\"!\" (ExplicitLink | ReferenceLink):a { a }") Rules[:_Link] = rule_info("Link", "(ExplicitLink | ReferenceLink | AutoLink)") Rules[:_ReferenceLink] = rule_info("ReferenceLink", "(ReferenceLinkDouble | ReferenceLinkSingle)") Rules[:_ReferenceLinkDouble] = rule_info("ReferenceLinkDouble", "Label:content < Spnl > !\"[]\" Label:label { link_to content, label, text }") Rules[:_ReferenceLinkSingle] = rule_info("ReferenceLinkSingle", "Label:content < (Spnl \"[]\")? > { link_to content, content, text }") Rules[:_ExplicitLink] = rule_info("ExplicitLink", "Label:l Spnl \"(\" Sp Source:s Spnl Title Sp \")\" { \"{\#{l}}[\#{s}]\" }") Rules[:_Source] = rule_info("Source", "(\"<\" < SourceContents > \">\" | < SourceContents >) { text }") Rules[:_SourceContents] = rule_info("SourceContents", "(((!\"(\" !\")\" !\">\" Nonspacechar)+ | \"(\" SourceContents \")\")* | \"\")") Rules[:_Title] = rule_info("Title", "(TitleSingle | TitleDouble | \"\"):a { a }") Rules[:_TitleSingle] = rule_info("TitleSingle", "\"'\" (!(\"'\" Sp (\")\" | Newline)) .)* \"'\"") Rules[:_TitleDouble] = rule_info("TitleDouble", "\"\\\"\" (!(\"\\\"\" Sp (\")\" | Newline)) .)* \"\\\"\"") Rules[:_AutoLink] = rule_info("AutoLink", "(AutoLinkUrl | AutoLinkEmail)") Rules[:_AutoLinkUrl] = rule_info("AutoLinkUrl", "\"<\" < /[A-Za-z]+/ \"://\" (!Newline !\">\" .)+ > \">\" { text }") Rules[:_AutoLinkEmail] = rule_info("AutoLinkEmail", "\"<\" \"mailto:\"? < /[\\w+.\\/!%~$-]+/i \"@\" (!Newline !\">\" .)+ > \">\" { \"mailto:\#{text}\" }") Rules[:_Reference] = rule_info("Reference", "NonindentSpace !\"[]\" Label:label \":\" Spnl RefSrc:link RefTitle BlankLine+ { \# TODO use title reference label, link nil }") Rules[:_Label] = rule_info("Label", "\"[\" (!\"^\" &{ notes? } | &. &{ !notes? }) StartList:a (!\"]\" Inline:l { a << l })* \"]\" { a.join.gsub(/\\s+/, ' ') }") Rules[:_RefSrc] = rule_info("RefSrc", "< Nonspacechar+ > { text }") Rules[:_RefTitle] = rule_info("RefTitle", "(RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle)") Rules[:_EmptyTitle] = rule_info("EmptyTitle", "\"\"") Rules[:_RefTitleSingle] = rule_info("RefTitleSingle", "Spnl \"'\" < (!(\"'\" Sp Newline | Newline) .)* > \"'\" { text }") Rules[:_RefTitleDouble] = rule_info("RefTitleDouble", "Spnl \"\\\"\" < (!(\"\\\"\" Sp Newline | Newline) .)* > \"\\\"\" { text }") Rules[:_RefTitleParens] = rule_info("RefTitleParens", "Spnl \"(\" < (!(\")\" Sp Newline | Newline) .)* > \")\" { text }") Rules[:_References] = rule_info("References", "(Reference | SkipBlock)*") Rules[:_Ticks1] = rule_info("Ticks1", "\"`\" !\"`\"") Rules[:_Ticks2] = rule_info("Ticks2", "\"``\" !\"`\"") Rules[:_Ticks3] = rule_info("Ticks3", "\"```\" !\"`\"") Rules[:_Ticks4] = rule_info("Ticks4", "\"````\" !\"`\"") Rules[:_Ticks5] = rule_info("Ticks5", "\"`````\" !\"`\"") Rules[:_Code] = rule_info("Code", "(Ticks1 Sp < ((!\"`\" Nonspacechar)+ | !Ticks1 \"`\"+ | !(Sp Ticks1) (Spacechar | Newline !BlankLine))+ > Sp Ticks1 | Ticks2 Sp < ((!\"`\" Nonspacechar)+ | !Ticks2 \"`\"+ | !(Sp Ticks2) (Spacechar | Newline !BlankLine))+ > Sp Ticks2 | Ticks3 Sp < ((!\"`\" Nonspacechar)+ | !Ticks3 \"`\"+ | !(Sp Ticks3) (Spacechar | Newline !BlankLine))+ > Sp Ticks3 | Ticks4 Sp < ((!\"`\" Nonspacechar)+ | !Ticks4 \"`\"+ | !(Sp Ticks4) (Spacechar | Newline !BlankLine))+ > Sp Ticks4 | Ticks5 Sp < ((!\"`\" Nonspacechar)+ | !Ticks5 \"`\"+ | !(Sp Ticks5) (Spacechar | Newline !BlankLine))+ > Sp Ticks5) { \"\#{text}\" }") Rules[:_RawHtml] = rule_info("RawHtml", "< (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end }") Rules[:_BlankLine] = rule_info("BlankLine", "Sp Newline { \"\\n\" }") Rules[:_Quoted] = rule_info("Quoted", "(\"\\\"\" (!\"\\\"\" .)* \"\\\"\" | \"'\" (!\"'\" .)* \"'\")") Rules[:_HtmlAttribute] = rule_info("HtmlAttribute", "(AlphanumericAscii | \"-\")+ Spnl (\"=\" Spnl (Quoted | (!\">\" Nonspacechar)+))? Spnl") Rules[:_HtmlComment] = rule_info("HtmlComment", "\"\" .)* \"-->\"") Rules[:_HtmlTag] = rule_info("HtmlTag", "\"<\" Spnl \"/\"? AlphanumericAscii+ Spnl HtmlAttribute* \"/\"? Spnl \">\"") Rules[:_Eof] = rule_info("Eof", "!.") Rules[:_Nonspacechar] = rule_info("Nonspacechar", "!Spacechar !Newline .") Rules[:_Sp] = rule_info("Sp", "Spacechar*") Rules[:_Spnl] = rule_info("Spnl", "Sp (Newline Sp)?") Rules[:_SpecialChar] = rule_info("SpecialChar", "(\"*\" | \"_\" | \"`\" | \"&\" | \"[\" | \"]\" | \"(\" | \")\" | \"<\" | \"!\" | \"\#\" | \"\\\\\" | \"'\" | \"\\\"\" | ExtendedSpecialChar)") Rules[:_NormalChar] = rule_info("NormalChar", "!(SpecialChar | Spacechar | Newline) .") Rules[:_Digit] = rule_info("Digit", "[0-9]") Rules[:_Alphanumeric] = rule_info("Alphanumeric", "%literals.Alphanumeric") Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "%literals.AlphanumericAscii") Rules[:_BOM] = rule_info("BOM", "%literals.BOM") Rules[:_Newline] = rule_info("Newline", "%literals.Newline") Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "%literals.NonAlphanumeric") Rules[:_Spacechar] = rule_info("Spacechar", "%literals.Spacechar") Rules[:_HexEntity] = rule_info("HexEntity", "\"&\" \"\#\" /[Xx]/ < /[0-9a-fA-F]+/ > \";\" { [text.to_i(16)].pack 'U' }") Rules[:_DecEntity] = rule_info("DecEntity", "\"&\" \"\#\" < /[0-9]+/ > \";\" { [text.to_i].pack 'U' }") Rules[:_CharEntity] = rule_info("CharEntity", "\"&\" < /[A-Za-z0-9]+/ > \";\" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else \"&\#{text};\" end }") Rules[:_NonindentSpace] = rule_info("NonindentSpace", "(\" \" | \" \" | \" \" | \"\")") Rules[:_Indent] = rule_info("Indent", "(\"\\t\" | \" \")") Rules[:_IndentedLine] = rule_info("IndentedLine", "Indent Line") Rules[:_OptionallyIndentedLine] = rule_info("OptionallyIndentedLine", "Indent? Line") Rules[:_StartList] = rule_info("StartList", "&. { [] }") Rules[:_Line] = rule_info("Line", "RawLine:a { a }") Rules[:_RawLine] = rule_info("RawLine", "(< (!\"\r\" !\"\\n\" .)* Newline > | < .+ > Eof) { text }") Rules[:_SkipBlock] = rule_info("SkipBlock", "(HtmlBlock | (!\"\#\" !SetextBottom1 !SetextBottom2 !BlankLine RawLine)+ BlankLine* | BlankLine+ | RawLine)") Rules[:_ExtendedSpecialChar] = rule_info("ExtendedSpecialChar", "&{ notes? } \"^\"") Rules[:_NoteReference] = rule_info("NoteReference", "&{ notes? } RawNoteReference:ref { note_for ref }") Rules[:_RawNoteReference] = rule_info("RawNoteReference", "\"[^\" < (!Newline !\"]\" .)+ > \"]\" { text }") Rules[:_Note] = rule_info("Note", "&{ notes? } NonindentSpace RawNoteReference:ref \":\" Sp StartList:a RawNoteBlock (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }") Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }") Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*") Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "StartList:a (!BlankLine OptionallyIndentedLine:l { a << l })+ < BlankLine* > { a << text } { a }") Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (Sp StrChunk:format)? Spnl < ((!\"`\" Nonspacechar)+ | !Ticks3 \"`\"+ | Spacechar | Newline)+ > Ticks3 Sp Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim }") Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }") Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }") Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label Sp Newline { label }") Rules[:_DefinitionListDefinition] = rule_info("DefinitionListDefinition", "NonindentSpace \":\" Space Inlines:a BlankLine+ { paragraph a }") # :startdoc: end rdoc/generator.rb000064400000003344147635155430010027 0ustar00## # RDoc uses generators to turn parsed source code in the form of an # RDoc::CodeObject tree into some form of output. RDoc comes with the HTML # generator RDoc::Generator::Darkfish and an ri data generator # RDoc::Generator::RI. # # == Registering a Generator # # Generators are registered by calling RDoc::RDoc.add_generator with the class # of the generator: # # class My::Awesome::Generator # RDoc::RDoc.add_generator self # end # # == Adding Options to +rdoc+ # # Before option processing in +rdoc+, RDoc::Options will call ::setup_options # on the generator class with an RDoc::Options instance. The generator can # use RDoc::Options#option_parser to add command-line options to the +rdoc+ # tool. See RDoc::Options@Custom+Options for an example and see OptionParser # for details on how to add options. # # You can extend the RDoc::Options instance with additional accessors for your # generator. # # == Generator Instantiation # # After parsing, RDoc::RDoc will instantiate a generator by calling # #initialize with an RDoc::Store instance and an RDoc::Options instance. # # The RDoc::Store instance holds documentation for parsed source code. In # RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading # a generator from RDoc 3 and earlier you should only need to replace # RDoc::TopLevel with the store instance. # # RDoc will then call #generate on the generator instance. You can use the # various methods on RDoc::Store and in the RDoc::CodeObject tree to create # your desired output format. module RDoc::Generator autoload :Markup, 'rdoc/generator/markup' autoload :Darkfish, 'rdoc/generator/darkfish' autoload :JsonIndex, 'rdoc/generator/json_index' autoload :RI, 'rdoc/generator/ri' end rdoc/markdown/literals_1_9.rb000064400000021734147635155430012155 0ustar00# coding: UTF-8 # :markup: markdown ## #-- # This set of literals is for ruby 1.9 regular expressions and gives full # unicode support. # # Unlike peg-markdown, this set of literals recognizes Unicode alphanumeric # characters, newlines and spaces. class RDoc::Markdown::Literals # :stopdoc: # This is distinct from setup_parser so that a standalone parser # can redefine #initialize and still have access to the proper # parser setup code. def initialize(str, debug=false) setup_parser(str, debug) end # Prepares for parsing +str+. If you define a custom initialize you must # call this method before #parse def setup_parser(str, debug=false) @string = str @pos = 0 @memoizations = Hash.new { |h,k| h[k] = {} } @result = nil @failed_rule = nil @failing_rule_offset = -1 setup_foreign_grammar end attr_reader :string attr_reader :failing_rule_offset attr_accessor :result, :pos def current_column(target=pos) if c = string.rindex("\n", target-1) return target - c - 1 end target + 1 end def current_line(target=pos) cur_offset = 0 cur_line = 0 string.each_line do |line| cur_line += 1 cur_offset += line.size return cur_line if cur_offset >= target end -1 end def lines lines = [] string.each_line { |l| lines << l } lines end def get_text(start) @string[start..@pos-1] end def show_pos width = 10 if @pos < width "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")" else "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")" end end def failure_info l = current_line @failing_rule_offset c = current_column @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'" else "line #{l}, column #{c}: failed rule '#{@failed_rule}'" end end def failure_caret l = current_line @failing_rule_offset c = current_column @failing_rule_offset line = lines[l-1] "#{line}\n#{' ' * (c - 1)}^" end def failure_character l = current_line @failing_rule_offset c = current_column @failing_rule_offset lines[l-1][c-1, 1] end def failure_oneline l = current_line @failing_rule_offset c = current_column @failing_rule_offset char = lines[l-1][c-1, 1] if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" else "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" end end class ParseError < RuntimeError end def raise_error raise ParseError, failure_oneline end def show_error(io=STDOUT) error_pos = @failing_rule_offset line_no = current_line(error_pos) col_no = current_column(error_pos) io.puts "On line #{line_no}, column #{col_no}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')" else io.puts "Failed to match rule '#{@failed_rule}'" end io.puts "Got: #{string[error_pos,1].inspect}" line = lines[line_no-1] io.puts "=> #{line}" io.print(" " * (col_no + 3)) io.puts "^" end def set_failed_rule(name) if @pos > @failing_rule_offset @failed_rule = name @failing_rule_offset = @pos end end attr_reader :failed_rule def match_string(str) len = str.size if @string[pos,len] == str @pos += len return str end return nil end def scan(reg) if m = reg.match(@string[@pos..-1]) width = m.end(0) @pos += width return true end return nil end if "".respond_to? :getbyte def get_byte if @pos >= @string.size return nil end s = @string.getbyte @pos @pos += 1 s end else def get_byte if @pos >= @string.size return nil end s = @string[@pos] @pos += 1 s end end def parse(rule=nil) # We invoke the rules indirectly via apply # instead of by just calling them as methods because # if the rules use left recursion, apply needs to # manage that. if !rule apply(:_root) else method = rule.gsub("-","_hyphen_") apply :"_#{method}" end end class MemoEntry def initialize(ans, pos) @ans = ans @pos = pos @result = nil @set = false @left_rec = false end attr_reader :ans, :pos, :result, :set attr_accessor :left_rec def move!(ans, pos, result) @ans = ans @pos = pos @result = result @set = true @left_rec = false end end def external_invoke(other, rule, *args) old_pos = @pos old_string = @string @pos = other.pos @string = other.string begin if val = __send__(rule, *args) other.pos = @pos other.result = @result else other.set_failed_rule "#{self.class}##{rule}" end val ensure @pos = old_pos @string = old_string end end def apply_with_args(rule, *args) memo_key = [rule, args] if m = @memoizations[memo_key][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[memo_key][@pos] = m start_pos = @pos ans = __send__ rule, *args lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, args, start_pos, m) else return ans end return ans end end def apply(rule) if m = @memoizations[rule][@pos] @pos = m.pos if !m.set m.left_rec = true return nil end @result = m.result return m.ans else m = MemoEntry.new(nil, @pos) @memoizations[rule][@pos] = m start_pos = @pos ans = __send__ rule lr = m.left_rec m.move! ans, @pos, @result # Don't bother trying to grow the left recursion # if it's failing straight away (thus there is no seed) if ans and lr return grow_lr(rule, nil, start_pos, m) else return ans end return ans end end def grow_lr(rule, args, start_pos, m) while true @pos = start_pos @result = m.result if args ans = __send__ rule, *args else ans = __send__ rule end return nil unless ans break if @pos <= m.pos m.move! ans, @pos, @result end @result = m.result @pos = m.pos return m.ans end class RuleInfo def initialize(name, rendered) @name = name @rendered = rendered end attr_reader :name, :rendered end def self.rule_info(name, rendered) RuleInfo.new(name, rendered) end # :startdoc: # :stopdoc: def setup_foreign_grammar; end # Alphanumeric = /\p{Word}/ def _Alphanumeric _tmp = scan(/\A(?-mix:\p{Word})/) set_failed_rule :_Alphanumeric unless _tmp return _tmp end # AlphanumericAscii = /[A-Za-z0-9]/ def _AlphanumericAscii _tmp = scan(/\A(?-mix:[A-Za-z0-9])/) set_failed_rule :_AlphanumericAscii unless _tmp return _tmp end # BOM = "uFEFF" def _BOM _tmp = match_string("uFEFF") set_failed_rule :_BOM unless _tmp return _tmp end # Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ def _Newline _tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/) set_failed_rule :_Newline unless _tmp return _tmp end # NonAlphanumeric = /\p{^Word}/ def _NonAlphanumeric _tmp = scan(/\A(?-mix:\p{^Word})/) set_failed_rule :_NonAlphanumeric unless _tmp return _tmp end # Spacechar = /\t|\p{Zs}/ def _Spacechar _tmp = scan(/\A(?-mix:\t|\p{Zs})/) set_failed_rule :_Spacechar unless _tmp return _tmp end Rules = {} Rules[:_Alphanumeric] = rule_info("Alphanumeric", "/\\p{Word}/") Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "/[A-Za-z0-9]/") Rules[:_BOM] = rule_info("BOM", "\"uFEFF\"") Rules[:_Newline] = rule_info("Newline", "/\\n|\\r\\n?|\\p{Zl}|\\p{Zp}/") Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "/\\p{^Word}/") Rules[:_Spacechar] = rule_info("Spacechar", "/\\t|\\p{Zs}/") # :startdoc: end rdoc/markdown/entities.rb000064400000154003147635155430011506 0ustar00## # HTML entity name map for RDoc::Markdown RDoc::Markdown::HTML_ENTITIES = { "AElig" => [0x000C6], "AMP" => [0x00026], "Aacute" => [0x000C1], "Abreve" => [0x00102], "Acirc" => [0x000C2], "Acy" => [0x00410], "Afr" => [0x1D504], "Agrave" => [0x000C0], "Alpha" => [0x00391], "Amacr" => [0x00100], "And" => [0x02A53], "Aogon" => [0x00104], "Aopf" => [0x1D538], "ApplyFunction" => [0x02061], "Aring" => [0x000C5], "Ascr" => [0x1D49C], "Assign" => [0x02254], "Atilde" => [0x000C3], "Auml" => [0x000C4], "Backslash" => [0x02216], "Barv" => [0x02AE7], "Barwed" => [0x02306], "Bcy" => [0x00411], "Because" => [0x02235], "Bernoullis" => [0x0212C], "Beta" => [0x00392], "Bfr" => [0x1D505], "Bopf" => [0x1D539], "Breve" => [0x002D8], "Bscr" => [0x0212C], "Bumpeq" => [0x0224E], "CHcy" => [0x00427], "COPY" => [0x000A9], "Cacute" => [0x00106], "Cap" => [0x022D2], "CapitalDifferentialD" => [0x02145], "Cayleys" => [0x0212D], "Ccaron" => [0x0010C], "Ccedil" => [0x000C7], "Ccirc" => [0x00108], "Cconint" => [0x02230], "Cdot" => [0x0010A], "Cedilla" => [0x000B8], "CenterDot" => [0x000B7], "Cfr" => [0x0212D], "Chi" => [0x003A7], "CircleDot" => [0x02299], "CircleMinus" => [0x02296], "CirclePlus" => [0x02295], "CircleTimes" => [0x02297], "ClockwiseContourIntegral" => [0x02232], "CloseCurlyDoubleQuote" => [0x0201D], "CloseCurlyQuote" => [0x02019], "Colon" => [0x02237], "Colone" => [0x02A74], "Congruent" => [0x02261], "Conint" => [0x0222F], "ContourIntegral" => [0x0222E], "Copf" => [0x02102], "Coproduct" => [0x02210], "CounterClockwiseContourIntegral" => [0x02233], "Cross" => [0x02A2F], "Cscr" => [0x1D49E], "Cup" => [0x022D3], "CupCap" => [0x0224D], "DD" => [0x02145], "DDotrahd" => [0x02911], "DJcy" => [0x00402], "DScy" => [0x00405], "DZcy" => [0x0040F], "Dagger" => [0x02021], "Darr" => [0x021A1], "Dashv" => [0x02AE4], "Dcaron" => [0x0010E], "Dcy" => [0x00414], "Del" => [0x02207], "Delta" => [0x00394], "Dfr" => [0x1D507], "DiacriticalAcute" => [0x000B4], "DiacriticalDot" => [0x002D9], "DiacriticalDoubleAcute" => [0x002DD], "DiacriticalGrave" => [0x00060], "DiacriticalTilde" => [0x002DC], "Diamond" => [0x022C4], "DifferentialD" => [0x02146], "Dopf" => [0x1D53B], "Dot" => [0x000A8], "DotDot" => [0x020DC], "DotEqual" => [0x02250], "DoubleContourIntegral" => [0x0222F], "DoubleDot" => [0x000A8], "DoubleDownArrow" => [0x021D3], "DoubleLeftArrow" => [0x021D0], "DoubleLeftRightArrow" => [0x021D4], "DoubleLeftTee" => [0x02AE4], "DoubleLongLeftArrow" => [0x027F8], "DoubleLongLeftRightArrow" => [0x027FA], "DoubleLongRightArrow" => [0x027F9], "DoubleRightArrow" => [0x021D2], "DoubleRightTee" => [0x022A8], "DoubleUpArrow" => [0x021D1], "DoubleUpDownArrow" => [0x021D5], "DoubleVerticalBar" => [0x02225], "DownArrow" => [0x02193], "DownArrowBar" => [0x02913], "DownArrowUpArrow" => [0x021F5], "DownBreve" => [0x00311], "DownLeftRightVector" => [0x02950], "DownLeftTeeVector" => [0x0295E], "DownLeftVector" => [0x021BD], "DownLeftVectorBar" => [0x02956], "DownRightTeeVector" => [0x0295F], "DownRightVector" => [0x021C1], "DownRightVectorBar" => [0x02957], "DownTee" => [0x022A4], "DownTeeArrow" => [0x021A7], "Downarrow" => [0x021D3], "Dscr" => [0x1D49F], "Dstrok" => [0x00110], "ENG" => [0x0014A], "ETH" => [0x000D0], "Eacute" => [0x000C9], "Ecaron" => [0x0011A], "Ecirc" => [0x000CA], "Ecy" => [0x0042D], "Edot" => [0x00116], "Efr" => [0x1D508], "Egrave" => [0x000C8], "Element" => [0x02208], "Emacr" => [0x00112], "EmptySmallSquare" => [0x025FB], "EmptyVerySmallSquare" => [0x025AB], "Eogon" => [0x00118], "Eopf" => [0x1D53C], "Epsilon" => [0x00395], "Equal" => [0x02A75], "EqualTilde" => [0x02242], "Equilibrium" => [0x021CC], "Escr" => [0x02130], "Esim" => [0x02A73], "Eta" => [0x00397], "Euml" => [0x000CB], "Exists" => [0x02203], "ExponentialE" => [0x02147], "Fcy" => [0x00424], "Ffr" => [0x1D509], "FilledSmallSquare" => [0x025FC], "FilledVerySmallSquare" => [0x025AA], "Fopf" => [0x1D53D], "ForAll" => [0x02200], "Fouriertrf" => [0x02131], "Fscr" => [0x02131], "GJcy" => [0x00403], "GT" => [0x0003E], "Gamma" => [0x00393], "Gammad" => [0x003DC], "Gbreve" => [0x0011E], "Gcedil" => [0x00122], "Gcirc" => [0x0011C], "Gcy" => [0x00413], "Gdot" => [0x00120], "Gfr" => [0x1D50A], "Gg" => [0x022D9], "Gopf" => [0x1D53E], "GreaterEqual" => [0x02265], "GreaterEqualLess" => [0x022DB], "GreaterFullEqual" => [0x02267], "GreaterGreater" => [0x02AA2], "GreaterLess" => [0x02277], "GreaterSlantEqual" => [0x02A7E], "GreaterTilde" => [0x02273], "Gscr" => [0x1D4A2], "Gt" => [0x0226B], "HARDcy" => [0x0042A], "Hacek" => [0x002C7], "Hat" => [0x0005E], "Hcirc" => [0x00124], "Hfr" => [0x0210C], "HilbertSpace" => [0x0210B], "Hopf" => [0x0210D], "HorizontalLine" => [0x02500], "Hscr" => [0x0210B], "Hstrok" => [0x00126], "HumpDownHump" => [0x0224E], "HumpEqual" => [0x0224F], "IEcy" => [0x00415], "IJlig" => [0x00132], "IOcy" => [0x00401], "Iacute" => [0x000CD], "Icirc" => [0x000CE], "Icy" => [0x00418], "Idot" => [0x00130], "Ifr" => [0x02111], "Igrave" => [0x000CC], "Im" => [0x02111], "Imacr" => [0x0012A], "ImaginaryI" => [0x02148], "Implies" => [0x021D2], "Int" => [0x0222C], "Integral" => [0x0222B], "Intersection" => [0x022C2], "InvisibleComma" => [0x02063], "InvisibleTimes" => [0x02062], "Iogon" => [0x0012E], "Iopf" => [0x1D540], "Iota" => [0x00399], "Iscr" => [0x02110], "Itilde" => [0x00128], "Iukcy" => [0x00406], "Iuml" => [0x000CF], "Jcirc" => [0x00134], "Jcy" => [0x00419], "Jfr" => [0x1D50D], "Jopf" => [0x1D541], "Jscr" => [0x1D4A5], "Jsercy" => [0x00408], "Jukcy" => [0x00404], "KHcy" => [0x00425], "KJcy" => [0x0040C], "Kappa" => [0x0039A], "Kcedil" => [0x00136], "Kcy" => [0x0041A], "Kfr" => [0x1D50E], "Kopf" => [0x1D542], "Kscr" => [0x1D4A6], "LJcy" => [0x00409], "LT" => [0x0003C], "Lacute" => [0x00139], "Lambda" => [0x0039B], "Lang" => [0x027EA], "Laplacetrf" => [0x02112], "Larr" => [0x0219E], "Lcaron" => [0x0013D], "Lcedil" => [0x0013B], "Lcy" => [0x0041B], "LeftAngleBracket" => [0x027E8], "LeftArrow" => [0x02190], "LeftArrowBar" => [0x021E4], "LeftArrowRightArrow" => [0x021C6], "LeftCeiling" => [0x02308], "LeftDoubleBracket" => [0x027E6], "LeftDownTeeVector" => [0x02961], "LeftDownVector" => [0x021C3], "LeftDownVectorBar" => [0x02959], "LeftFloor" => [0x0230A], "LeftRightArrow" => [0x02194], "LeftRightVector" => [0x0294E], "LeftTee" => [0x022A3], "LeftTeeArrow" => [0x021A4], "LeftTeeVector" => [0x0295A], "LeftTriangle" => [0x022B2], "LeftTriangleBar" => [0x029CF], "LeftTriangleEqual" => [0x022B4], "LeftUpDownVector" => [0x02951], "LeftUpTeeVector" => [0x02960], "LeftUpVector" => [0x021BF], "LeftUpVectorBar" => [0x02958], "LeftVector" => [0x021BC], "LeftVectorBar" => [0x02952], "Leftarrow" => [0x021D0], "Leftrightarrow" => [0x021D4], "LessEqualGreater" => [0x022DA], "LessFullEqual" => [0x02266], "LessGreater" => [0x02276], "LessLess" => [0x02AA1], "LessSlantEqual" => [0x02A7D], "LessTilde" => [0x02272], "Lfr" => [0x1D50F], "Ll" => [0x022D8], "Lleftarrow" => [0x021DA], "Lmidot" => [0x0013F], "LongLeftArrow" => [0x027F5], "LongLeftRightArrow" => [0x027F7], "LongRightArrow" => [0x027F6], "Longleftarrow" => [0x027F8], "Longleftrightarrow" => [0x027FA], "Longrightarrow" => [0x027F9], "Lopf" => [0x1D543], "LowerLeftArrow" => [0x02199], "LowerRightArrow" => [0x02198], "Lscr" => [0x02112], "Lsh" => [0x021B0], "Lstrok" => [0x00141], "Lt" => [0x0226A], "Map" => [0x02905], "Mcy" => [0x0041C], "MediumSpace" => [0x0205F], "Mellintrf" => [0x02133], "Mfr" => [0x1D510], "MinusPlus" => [0x02213], "Mopf" => [0x1D544], "Mscr" => [0x02133], "Mu" => [0x0039C], "NJcy" => [0x0040A], "Nacute" => [0x00143], "Ncaron" => [0x00147], "Ncedil" => [0x00145], "Ncy" => [0x0041D], "NegativeMediumSpace" => [0x0200B], "NegativeThickSpace" => [0x0200B], "NegativeThinSpace" => [0x0200B], "NegativeVeryThinSpace" => [0x0200B], "NestedGreaterGreater" => [0x0226B], "NestedLessLess" => [0x0226A], "NewLine" => [0x0000A], "Nfr" => [0x1D511], "NoBreak" => [0x02060], "NonBreakingSpace" => [0x000A0], "Nopf" => [0x02115], "Not" => [0x02AEC], "NotCongruent" => [0x02262], "NotCupCap" => [0x0226D], "NotDoubleVerticalBar" => [0x02226], "NotElement" => [0x02209], "NotEqual" => [0x02260], "NotEqualTilde" => [0x02242, 0x00338], "NotExists" => [0x02204], "NotGreater" => [0x0226F], "NotGreaterEqual" => [0x02271], "NotGreaterFullEqual" => [0x02267, 0x00338], "NotGreaterGreater" => [0x0226B, 0x00338], "NotGreaterLess" => [0x02279], "NotGreaterSlantEqual" => [0x02A7E, 0x00338], "NotGreaterTilde" => [0x02275], "NotHumpDownHump" => [0x0224E, 0x00338], "NotHumpEqual" => [0x0224F, 0x00338], "NotLeftTriangle" => [0x022EA], "NotLeftTriangleBar" => [0x029CF, 0x00338], "NotLeftTriangleEqual" => [0x022EC], "NotLess" => [0x0226E], "NotLessEqual" => [0x02270], "NotLessGreater" => [0x02278], "NotLessLess" => [0x0226A, 0x00338], "NotLessSlantEqual" => [0x02A7D, 0x00338], "NotLessTilde" => [0x02274], "NotNestedGreaterGreater" => [0x02AA2, 0x00338], "NotNestedLessLess" => [0x02AA1, 0x00338], "NotPrecedes" => [0x02280], "NotPrecedesEqual" => [0x02AAF, 0x00338], "NotPrecedesSlantEqual" => [0x022E0], "NotReverseElement" => [0x0220C], "NotRightTriangle" => [0x022EB], "NotRightTriangleBar" => [0x029D0, 0x00338], "NotRightTriangleEqual" => [0x022ED], "NotSquareSubset" => [0x0228F, 0x00338], "NotSquareSubsetEqual" => [0x022E2], "NotSquareSuperset" => [0x02290, 0x00338], "NotSquareSupersetEqual" => [0x022E3], "NotSubset" => [0x02282, 0x020D2], "NotSubsetEqual" => [0x02288], "NotSucceeds" => [0x02281], "NotSucceedsEqual" => [0x02AB0, 0x00338], "NotSucceedsSlantEqual" => [0x022E1], "NotSucceedsTilde" => [0x0227F, 0x00338], "NotSuperset" => [0x02283, 0x020D2], "NotSupersetEqual" => [0x02289], "NotTilde" => [0x02241], "NotTildeEqual" => [0x02244], "NotTildeFullEqual" => [0x02247], "NotTildeTilde" => [0x02249], "NotVerticalBar" => [0x02224], "Nscr" => [0x1D4A9], "Ntilde" => [0x000D1], "Nu" => [0x0039D], "OElig" => [0x00152], "Oacute" => [0x000D3], "Ocirc" => [0x000D4], "Ocy" => [0x0041E], "Odblac" => [0x00150], "Ofr" => [0x1D512], "Ograve" => [0x000D2], "Omacr" => [0x0014C], "Omega" => [0x003A9], "Omicron" => [0x0039F], "Oopf" => [0x1D546], "OpenCurlyDoubleQuote" => [0x0201C], "OpenCurlyQuote" => [0x02018], "Or" => [0x02A54], "Oscr" => [0x1D4AA], "Oslash" => [0x000D8], "Otilde" => [0x000D5], "Otimes" => [0x02A37], "Ouml" => [0x000D6], "OverBar" => [0x0203E], "OverBrace" => [0x023DE], "OverBracket" => [0x023B4], "OverParenthesis" => [0x023DC], "PartialD" => [0x02202], "Pcy" => [0x0041F], "Pfr" => [0x1D513], "Phi" => [0x003A6], "Pi" => [0x003A0], "PlusMinus" => [0x000B1], "Poincareplane" => [0x0210C], "Popf" => [0x02119], "Pr" => [0x02ABB], "Precedes" => [0x0227A], "PrecedesEqual" => [0x02AAF], "PrecedesSlantEqual" => [0x0227C], "PrecedesTilde" => [0x0227E], "Prime" => [0x02033], "Product" => [0x0220F], "Proportion" => [0x02237], "Proportional" => [0x0221D], "Pscr" => [0x1D4AB], "Psi" => [0x003A8], "QUOT" => [0x00022], "Qfr" => [0x1D514], "Qopf" => [0x0211A], "Qscr" => [0x1D4AC], "RBarr" => [0x02910], "REG" => [0x000AE], "Racute" => [0x00154], "Rang" => [0x027EB], "Rarr" => [0x021A0], "Rarrtl" => [0x02916], "Rcaron" => [0x00158], "Rcedil" => [0x00156], "Rcy" => [0x00420], "Re" => [0x0211C], "ReverseElement" => [0x0220B], "ReverseEquilibrium" => [0x021CB], "ReverseUpEquilibrium" => [0x0296F], "Rfr" => [0x0211C], "Rho" => [0x003A1], "RightAngleBracket" => [0x027E9], "RightArrow" => [0x02192], "RightArrowBar" => [0x021E5], "RightArrowLeftArrow" => [0x021C4], "RightCeiling" => [0x02309], "RightDoubleBracket" => [0x027E7], "RightDownTeeVector" => [0x0295D], "RightDownVector" => [0x021C2], "RightDownVectorBar" => [0x02955], "RightFloor" => [0x0230B], "RightTee" => [0x022A2], "RightTeeArrow" => [0x021A6], "RightTeeVector" => [0x0295B], "RightTriangle" => [0x022B3], "RightTriangleBar" => [0x029D0], "RightTriangleEqual" => [0x022B5], "RightUpDownVector" => [0x0294F], "RightUpTeeVector" => [0x0295C], "RightUpVector" => [0x021BE], "RightUpVectorBar" => [0x02954], "RightVector" => [0x021C0], "RightVectorBar" => [0x02953], "Rightarrow" => [0x021D2], "Ropf" => [0x0211D], "RoundImplies" => [0x02970], "Rrightarrow" => [0x021DB], "Rscr" => [0x0211B], "Rsh" => [0x021B1], "RuleDelayed" => [0x029F4], "SHCHcy" => [0x00429], "SHcy" => [0x00428], "SOFTcy" => [0x0042C], "Sacute" => [0x0015A], "Sc" => [0x02ABC], "Scaron" => [0x00160], "Scedil" => [0x0015E], "Scirc" => [0x0015C], "Scy" => [0x00421], "Sfr" => [0x1D516], "ShortDownArrow" => [0x02193], "ShortLeftArrow" => [0x02190], "ShortRightArrow" => [0x02192], "ShortUpArrow" => [0x02191], "Sigma" => [0x003A3], "SmallCircle" => [0x02218], "Sopf" => [0x1D54A], "Sqrt" => [0x0221A], "Square" => [0x025A1], "SquareIntersection" => [0x02293], "SquareSubset" => [0x0228F], "SquareSubsetEqual" => [0x02291], "SquareSuperset" => [0x02290], "SquareSupersetEqual" => [0x02292], "SquareUnion" => [0x02294], "Sscr" => [0x1D4AE], "Star" => [0x022C6], "Sub" => [0x022D0], "Subset" => [0x022D0], "SubsetEqual" => [0x02286], "Succeeds" => [0x0227B], "SucceedsEqual" => [0x02AB0], "SucceedsSlantEqual" => [0x0227D], "SucceedsTilde" => [0x0227F], "SuchThat" => [0x0220B], "Sum" => [0x02211], "Sup" => [0x022D1], "Superset" => [0x02283], "SupersetEqual" => [0x02287], "Supset" => [0x022D1], "THORN" => [0x000DE], "TRADE" => [0x02122], "TSHcy" => [0x0040B], "TScy" => [0x00426], "Tab" => [0x00009], "Tau" => [0x003A4], "Tcaron" => [0x00164], "Tcedil" => [0x00162], "Tcy" => [0x00422], "Tfr" => [0x1D517], "Therefore" => [0x02234], "Theta" => [0x00398], "ThickSpace" => [0x0205F, 0x0200A], "ThinSpace" => [0x02009], "Tilde" => [0x0223C], "TildeEqual" => [0x02243], "TildeFullEqual" => [0x02245], "TildeTilde" => [0x02248], "Topf" => [0x1D54B], "TripleDot" => [0x020DB], "Tscr" => [0x1D4AF], "Tstrok" => [0x00166], "Uacute" => [0x000DA], "Uarr" => [0x0219F], "Uarrocir" => [0x02949], "Ubrcy" => [0x0040E], "Ubreve" => [0x0016C], "Ucirc" => [0x000DB], "Ucy" => [0x00423], "Udblac" => [0x00170], "Ufr" => [0x1D518], "Ugrave" => [0x000D9], "Umacr" => [0x0016A], "UnderBar" => [0x0005F], "UnderBrace" => [0x023DF], "UnderBracket" => [0x023B5], "UnderParenthesis" => [0x023DD], "Union" => [0x022C3], "UnionPlus" => [0x0228E], "Uogon" => [0x00172], "Uopf" => [0x1D54C], "UpArrow" => [0x02191], "UpArrowBar" => [0x02912], "UpArrowDownArrow" => [0x021C5], "UpDownArrow" => [0x02195], "UpEquilibrium" => [0x0296E], "UpTee" => [0x022A5], "UpTeeArrow" => [0x021A5], "Uparrow" => [0x021D1], "Updownarrow" => [0x021D5], "UpperLeftArrow" => [0x02196], "UpperRightArrow" => [0x02197], "Upsi" => [0x003D2], "Upsilon" => [0x003A5], "Uring" => [0x0016E], "Uscr" => [0x1D4B0], "Utilde" => [0x00168], "Uuml" => [0x000DC], "VDash" => [0x022AB], "Vbar" => [0x02AEB], "Vcy" => [0x00412], "Vdash" => [0x022A9], "Vdashl" => [0x02AE6], "Vee" => [0x022C1], "Verbar" => [0x02016], "Vert" => [0x02016], "VerticalBar" => [0x02223], "VerticalLine" => [0x0007C], "VerticalSeparator" => [0x02758], "VerticalTilde" => [0x02240], "VeryThinSpace" => [0x0200A], "Vfr" => [0x1D519], "Vopf" => [0x1D54D], "Vscr" => [0x1D4B1], "Vvdash" => [0x022AA], "Wcirc" => [0x00174], "Wedge" => [0x022C0], "Wfr" => [0x1D51A], "Wopf" => [0x1D54E], "Wscr" => [0x1D4B2], "Xfr" => [0x1D51B], "Xi" => [0x0039E], "Xopf" => [0x1D54F], "Xscr" => [0x1D4B3], "YAcy" => [0x0042F], "YIcy" => [0x00407], "YUcy" => [0x0042E], "Yacute" => [0x000DD], "Ycirc" => [0x00176], "Ycy" => [0x0042B], "Yfr" => [0x1D51C], "Yopf" => [0x1D550], "Yscr" => [0x1D4B4], "Yuml" => [0x00178], "ZHcy" => [0x00416], "Zacute" => [0x00179], "Zcaron" => [0x0017D], "Zcy" => [0x00417], "Zdot" => [0x0017B], "ZeroWidthSpace" => [0x0200B], "Zeta" => [0x00396], "Zfr" => [0x02128], "Zopf" => [0x02124], "Zscr" => [0x1D4B5], "aacute" => [0x000E1], "abreve" => [0x00103], "ac" => [0x0223E], "acE" => [0x0223E, 0x00333], "acd" => [0x0223F], "acirc" => [0x000E2], "acute" => [0x000B4], "acy" => [0x00430], "aelig" => [0x000E6], "af" => [0x02061], "afr" => [0x1D51E], "agrave" => [0x000E0], "alefsym" => [0x02135], "aleph" => [0x02135], "alpha" => [0x003B1], "amacr" => [0x00101], "amalg" => [0x02A3F], "amp" => [0x00026], "and" => [0x02227], "andand" => [0x02A55], "andd" => [0x02A5C], "andslope" => [0x02A58], "andv" => [0x02A5A], "ang" => [0x02220], "ange" => [0x029A4], "angle" => [0x02220], "angmsd" => [0x02221], "angmsdaa" => [0x029A8], "angmsdab" => [0x029A9], "angmsdac" => [0x029AA], "angmsdad" => [0x029AB], "angmsdae" => [0x029AC], "angmsdaf" => [0x029AD], "angmsdag" => [0x029AE], "angmsdah" => [0x029AF], "angrt" => [0x0221F], "angrtvb" => [0x022BE], "angrtvbd" => [0x0299D], "angsph" => [0x02222], "angst" => [0x000C5], "angzarr" => [0x0237C], "aogon" => [0x00105], "aopf" => [0x1D552], "ap" => [0x02248], "apE" => [0x02A70], "apacir" => [0x02A6F], "ape" => [0x0224A], "apid" => [0x0224B], "apos" => [0x00027], "approx" => [0x02248], "approxeq" => [0x0224A], "aring" => [0x000E5], "ascr" => [0x1D4B6], "ast" => [0x0002A], "asymp" => [0x02248], "asympeq" => [0x0224D], "atilde" => [0x000E3], "auml" => [0x000E4], "awconint" => [0x02233], "awint" => [0x02A11], "bNot" => [0x02AED], "backcong" => [0x0224C], "backepsilon" => [0x003F6], "backprime" => [0x02035], "backsim" => [0x0223D], "backsimeq" => [0x022CD], "barvee" => [0x022BD], "barwed" => [0x02305], "barwedge" => [0x02305], "bbrk" => [0x023B5], "bbrktbrk" => [0x023B6], "bcong" => [0x0224C], "bcy" => [0x00431], "bdquo" => [0x0201E], "becaus" => [0x02235], "because" => [0x02235], "bemptyv" => [0x029B0], "bepsi" => [0x003F6], "bernou" => [0x0212C], "beta" => [0x003B2], "beth" => [0x02136], "between" => [0x0226C], "bfr" => [0x1D51F], "bigcap" => [0x022C2], "bigcirc" => [0x025EF], "bigcup" => [0x022C3], "bigodot" => [0x02A00], "bigoplus" => [0x02A01], "bigotimes" => [0x02A02], "bigsqcup" => [0x02A06], "bigstar" => [0x02605], "bigtriangledown" => [0x025BD], "bigtriangleup" => [0x025B3], "biguplus" => [0x02A04], "bigvee" => [0x022C1], "bigwedge" => [0x022C0], "bkarow" => [0x0290D], "blacklozenge" => [0x029EB], "blacksquare" => [0x025AA], "blacktriangle" => [0x025B4], "blacktriangledown" => [0x025BE], "blacktriangleleft" => [0x025C2], "blacktriangleright" => [0x025B8], "blank" => [0x02423], "blk12" => [0x02592], "blk14" => [0x02591], "blk34" => [0x02593], "block" => [0x02588], "bne" => [0x0003D, 0x020E5], "bnequiv" => [0x02261, 0x020E5], "bnot" => [0x02310], "bopf" => [0x1D553], "bot" => [0x022A5], "bottom" => [0x022A5], "bowtie" => [0x022C8], "boxDL" => [0x02557], "boxDR" => [0x02554], "boxDl" => [0x02556], "boxDr" => [0x02553], "boxH" => [0x02550], "boxHD" => [0x02566], "boxHU" => [0x02569], "boxHd" => [0x02564], "boxHu" => [0x02567], "boxUL" => [0x0255D], "boxUR" => [0x0255A], "boxUl" => [0x0255C], "boxUr" => [0x02559], "boxV" => [0x02551], "boxVH" => [0x0256C], "boxVL" => [0x02563], "boxVR" => [0x02560], "boxVh" => [0x0256B], "boxVl" => [0x02562], "boxVr" => [0x0255F], "boxbox" => [0x029C9], "boxdL" => [0x02555], "boxdR" => [0x02552], "boxdl" => [0x02510], "boxdr" => [0x0250C], "boxh" => [0x02500], "boxhD" => [0x02565], "boxhU" => [0x02568], "boxhd" => [0x0252C], "boxhu" => [0x02534], "boxminus" => [0x0229F], "boxplus" => [0x0229E], "boxtimes" => [0x022A0], "boxuL" => [0x0255B], "boxuR" => [0x02558], "boxul" => [0x02518], "boxur" => [0x02514], "boxv" => [0x02502], "boxvH" => [0x0256A], "boxvL" => [0x02561], "boxvR" => [0x0255E], "boxvh" => [0x0253C], "boxvl" => [0x02524], "boxvr" => [0x0251C], "bprime" => [0x02035], "breve" => [0x002D8], "brvbar" => [0x000A6], "bscr" => [0x1D4B7], "bsemi" => [0x0204F], "bsim" => [0x0223D], "bsime" => [0x022CD], "bsol" => [0x0005C], "bsolb" => [0x029C5], "bsolhsub" => [0x027C8], "bull" => [0x02022], "bullet" => [0x02022], "bump" => [0x0224E], "bumpE" => [0x02AAE], "bumpe" => [0x0224F], "bumpeq" => [0x0224F], "cacute" => [0x00107], "cap" => [0x02229], "capand" => [0x02A44], "capbrcup" => [0x02A49], "capcap" => [0x02A4B], "capcup" => [0x02A47], "capdot" => [0x02A40], "caps" => [0x02229, 0x0FE00], "caret" => [0x02041], "caron" => [0x002C7], "ccaps" => [0x02A4D], "ccaron" => [0x0010D], "ccedil" => [0x000E7], "ccirc" => [0x00109], "ccups" => [0x02A4C], "ccupssm" => [0x02A50], "cdot" => [0x0010B], "cedil" => [0x000B8], "cemptyv" => [0x029B2], "cent" => [0x000A2], "centerdot" => [0x000B7], "cfr" => [0x1D520], "chcy" => [0x00447], "check" => [0x02713], "checkmark" => [0x02713], "chi" => [0x003C7], "cir" => [0x025CB], "cirE" => [0x029C3], "circ" => [0x002C6], "circeq" => [0x02257], "circlearrowleft" => [0x021BA], "circlearrowright" => [0x021BB], "circledR" => [0x000AE], "circledS" => [0x024C8], "circledast" => [0x0229B], "circledcirc" => [0x0229A], "circleddash" => [0x0229D], "cire" => [0x02257], "cirfnint" => [0x02A10], "cirmid" => [0x02AEF], "cirscir" => [0x029C2], "clubs" => [0x02663], "clubsuit" => [0x02663], "colon" => [0x0003A], "colone" => [0x02254], "coloneq" => [0x02254], "comma" => [0x0002C], "commat" => [0x00040], "comp" => [0x02201], "compfn" => [0x02218], "complement" => [0x02201], "complexes" => [0x02102], "cong" => [0x02245], "congdot" => [0x02A6D], "conint" => [0x0222E], "copf" => [0x1D554], "coprod" => [0x02210], "copy" => [0x000A9], "copysr" => [0x02117], "crarr" => [0x021B5], "cross" => [0x02717], "cscr" => [0x1D4B8], "csub" => [0x02ACF], "csube" => [0x02AD1], "csup" => [0x02AD0], "csupe" => [0x02AD2], "ctdot" => [0x022EF], "cudarrl" => [0x02938], "cudarrr" => [0x02935], "cuepr" => [0x022DE], "cuesc" => [0x022DF], "cularr" => [0x021B6], "cularrp" => [0x0293D], "cup" => [0x0222A], "cupbrcap" => [0x02A48], "cupcap" => [0x02A46], "cupcup" => [0x02A4A], "cupdot" => [0x0228D], "cupor" => [0x02A45], "cups" => [0x0222A, 0x0FE00], "curarr" => [0x021B7], "curarrm" => [0x0293C], "curlyeqprec" => [0x022DE], "curlyeqsucc" => [0x022DF], "curlyvee" => [0x022CE], "curlywedge" => [0x022CF], "curren" => [0x000A4], "curvearrowleft" => [0x021B6], "curvearrowright" => [0x021B7], "cuvee" => [0x022CE], "cuwed" => [0x022CF], "cwconint" => [0x02232], "cwint" => [0x02231], "cylcty" => [0x0232D], "dArr" => [0x021D3], "dHar" => [0x02965], "dagger" => [0x02020], "daleth" => [0x02138], "darr" => [0x02193], "dash" => [0x02010], "dashv" => [0x022A3], "dbkarow" => [0x0290F], "dblac" => [0x002DD], "dcaron" => [0x0010F], "dcy" => [0x00434], "dd" => [0x02146], "ddagger" => [0x02021], "ddarr" => [0x021CA], "ddotseq" => [0x02A77], "deg" => [0x000B0], "delta" => [0x003B4], "demptyv" => [0x029B1], "dfisht" => [0x0297F], "dfr" => [0x1D521], "dharl" => [0x021C3], "dharr" => [0x021C2], "diam" => [0x022C4], "diamond" => [0x022C4], "diamondsuit" => [0x02666], "diams" => [0x02666], "die" => [0x000A8], "digamma" => [0x003DD], "disin" => [0x022F2], "div" => [0x000F7], "divide" => [0x000F7], "divideontimes" => [0x022C7], "divonx" => [0x022C7], "djcy" => [0x00452], "dlcorn" => [0x0231E], "dlcrop" => [0x0230D], "dollar" => [0x00024], "dopf" => [0x1D555], "dot" => [0x002D9], "doteq" => [0x02250], "doteqdot" => [0x02251], "dotminus" => [0x02238], "dotplus" => [0x02214], "dotsquare" => [0x022A1], "doublebarwedge" => [0x02306], "downarrow" => [0x02193], "downdownarrows" => [0x021CA], "downharpoonleft" => [0x021C3], "downharpoonright" => [0x021C2], "drbkarow" => [0x02910], "drcorn" => [0x0231F], "drcrop" => [0x0230C], "dscr" => [0x1D4B9], "dscy" => [0x00455], "dsol" => [0x029F6], "dstrok" => [0x00111], "dtdot" => [0x022F1], "dtri" => [0x025BF], "dtrif" => [0x025BE], "duarr" => [0x021F5], "duhar" => [0x0296F], "dwangle" => [0x029A6], "dzcy" => [0x0045F], "dzigrarr" => [0x027FF], "eDDot" => [0x02A77], "eDot" => [0x02251], "eacute" => [0x000E9], "easter" => [0x02A6E], "ecaron" => [0x0011B], "ecir" => [0x02256], "ecirc" => [0x000EA], "ecolon" => [0x02255], "ecy" => [0x0044D], "edot" => [0x00117], "ee" => [0x02147], "efDot" => [0x02252], "efr" => [0x1D522], "eg" => [0x02A9A], "egrave" => [0x000E8], "egs" => [0x02A96], "egsdot" => [0x02A98], "el" => [0x02A99], "elinters" => [0x023E7], "ell" => [0x02113], "els" => [0x02A95], "elsdot" => [0x02A97], "emacr" => [0x00113], "empty" => [0x02205], "emptyset" => [0x02205], "emptyv" => [0x02205], "emsp" => [0x02003], "emsp13" => [0x02004], "emsp14" => [0x02005], "eng" => [0x0014B], "ensp" => [0x02002], "eogon" => [0x00119], "eopf" => [0x1D556], "epar" => [0x022D5], "eparsl" => [0x029E3], "eplus" => [0x02A71], "epsi" => [0x003B5], "epsilon" => [0x003B5], "epsiv" => [0x003F5], "eqcirc" => [0x02256], "eqcolon" => [0x02255], "eqsim" => [0x02242], "eqslantgtr" => [0x02A96], "eqslantless" => [0x02A95], "equals" => [0x0003D], "equest" => [0x0225F], "equiv" => [0x02261], "equivDD" => [0x02A78], "eqvparsl" => [0x029E5], "erDot" => [0x02253], "erarr" => [0x02971], "escr" => [0x0212F], "esdot" => [0x02250], "esim" => [0x02242], "eta" => [0x003B7], "eth" => [0x000F0], "euml" => [0x000EB], "euro" => [0x020AC], "excl" => [0x00021], "exist" => [0x02203], "expectation" => [0x02130], "exponentiale" => [0x02147], "fallingdotseq" => [0x02252], "fcy" => [0x00444], "female" => [0x02640], "ffilig" => [0x0FB03], "fflig" => [0x0FB00], "ffllig" => [0x0FB04], "ffr" => [0x1D523], "filig" => [0x0FB01], "fjlig" => [0x00066, 0x0006A], "flat" => [0x0266D], "fllig" => [0x0FB02], "fltns" => [0x025B1], "fnof" => [0x00192], "fopf" => [0x1D557], "forall" => [0x02200], "fork" => [0x022D4], "forkv" => [0x02AD9], "fpartint" => [0x02A0D], "frac12" => [0x000BD], "frac13" => [0x02153], "frac14" => [0x000BC], "frac15" => [0x02155], "frac16" => [0x02159], "frac18" => [0x0215B], "frac23" => [0x02154], "frac25" => [0x02156], "frac34" => [0x000BE], "frac35" => [0x02157], "frac38" => [0x0215C], "frac45" => [0x02158], "frac56" => [0x0215A], "frac58" => [0x0215D], "frac78" => [0x0215E], "frasl" => [0x02044], "frown" => [0x02322], "fscr" => [0x1D4BB], "gE" => [0x02267], "gEl" => [0x02A8C], "gacute" => [0x001F5], "gamma" => [0x003B3], "gammad" => [0x003DD], "gap" => [0x02A86], "gbreve" => [0x0011F], "gcirc" => [0x0011D], "gcy" => [0x00433], "gdot" => [0x00121], "ge" => [0x02265], "gel" => [0x022DB], "geq" => [0x02265], "geqq" => [0x02267], "geqslant" => [0x02A7E], "ges" => [0x02A7E], "gescc" => [0x02AA9], "gesdot" => [0x02A80], "gesdoto" => [0x02A82], "gesdotol" => [0x02A84], "gesl" => [0x022DB, 0x0FE00], "gesles" => [0x02A94], "gfr" => [0x1D524], "gg" => [0x0226B], "ggg" => [0x022D9], "gimel" => [0x02137], "gjcy" => [0x00453], "gl" => [0x02277], "glE" => [0x02A92], "gla" => [0x02AA5], "glj" => [0x02AA4], "gnE" => [0x02269], "gnap" => [0x02A8A], "gnapprox" => [0x02A8A], "gne" => [0x02A88], "gneq" => [0x02A88], "gneqq" => [0x02269], "gnsim" => [0x022E7], "gopf" => [0x1D558], "grave" => [0x00060], "gscr" => [0x0210A], "gsim" => [0x02273], "gsime" => [0x02A8E], "gsiml" => [0x02A90], "gt" => [0x0003E], "gtcc" => [0x02AA7], "gtcir" => [0x02A7A], "gtdot" => [0x022D7], "gtlPar" => [0x02995], "gtquest" => [0x02A7C], "gtrapprox" => [0x02A86], "gtrarr" => [0x02978], "gtrdot" => [0x022D7], "gtreqless" => [0x022DB], "gtreqqless" => [0x02A8C], "gtrless" => [0x02277], "gtrsim" => [0x02273], "gvertneqq" => [0x02269, 0x0FE00], "gvnE" => [0x02269, 0x0FE00], "hArr" => [0x021D4], "hairsp" => [0x0200A], "half" => [0x000BD], "hamilt" => [0x0210B], "hardcy" => [0x0044A], "harr" => [0x02194], "harrcir" => [0x02948], "harrw" => [0x021AD], "hbar" => [0x0210F], "hcirc" => [0x00125], "hearts" => [0x02665], "heartsuit" => [0x02665], "hellip" => [0x02026], "hercon" => [0x022B9], "hfr" => [0x1D525], "hksearow" => [0x02925], "hkswarow" => [0x02926], "hoarr" => [0x021FF], "homtht" => [0x0223B], "hookleftarrow" => [0x021A9], "hookrightarrow" => [0x021AA], "hopf" => [0x1D559], "horbar" => [0x02015], "hscr" => [0x1D4BD], "hslash" => [0x0210F], "hstrok" => [0x00127], "hybull" => [0x02043], "hyphen" => [0x02010], "iacute" => [0x000ED], "ic" => [0x02063], "icirc" => [0x000EE], "icy" => [0x00438], "iecy" => [0x00435], "iexcl" => [0x000A1], "iff" => [0x021D4], "ifr" => [0x1D526], "igrave" => [0x000EC], "ii" => [0x02148], "iiiint" => [0x02A0C], "iiint" => [0x0222D], "iinfin" => [0x029DC], "iiota" => [0x02129], "ijlig" => [0x00133], "imacr" => [0x0012B], "image" => [0x02111], "imagline" => [0x02110], "imagpart" => [0x02111], "imath" => [0x00131], "imof" => [0x022B7], "imped" => [0x001B5], "in" => [0x02208], "incare" => [0x02105], "infin" => [0x0221E], "infintie" => [0x029DD], "inodot" => [0x00131], "int" => [0x0222B], "intcal" => [0x022BA], "integers" => [0x02124], "intercal" => [0x022BA], "intlarhk" => [0x02A17], "intprod" => [0x02A3C], "iocy" => [0x00451], "iogon" => [0x0012F], "iopf" => [0x1D55A], "iota" => [0x003B9], "iprod" => [0x02A3C], "iquest" => [0x000BF], "iscr" => [0x1D4BE], "isin" => [0x02208], "isinE" => [0x022F9], "isindot" => [0x022F5], "isins" => [0x022F4], "isinsv" => [0x022F3], "isinv" => [0x02208], "it" => [0x02062], "itilde" => [0x00129], "iukcy" => [0x00456], "iuml" => [0x000EF], "jcirc" => [0x00135], "jcy" => [0x00439], "jfr" => [0x1D527], "jmath" => [0x00237], "jopf" => [0x1D55B], "jscr" => [0x1D4BF], "jsercy" => [0x00458], "jukcy" => [0x00454], "kappa" => [0x003BA], "kappav" => [0x003F0], "kcedil" => [0x00137], "kcy" => [0x0043A], "kfr" => [0x1D528], "kgreen" => [0x00138], "khcy" => [0x00445], "kjcy" => [0x0045C], "kopf" => [0x1D55C], "kscr" => [0x1D4C0], "lAarr" => [0x021DA], "lArr" => [0x021D0], "lAtail" => [0x0291B], "lBarr" => [0x0290E], "lE" => [0x02266], "lEg" => [0x02A8B], "lHar" => [0x02962], "lacute" => [0x0013A], "laemptyv" => [0x029B4], "lagran" => [0x02112], "lambda" => [0x003BB], "lang" => [0x027E8], "langd" => [0x02991], "langle" => [0x027E8], "lap" => [0x02A85], "laquo" => [0x000AB], "larr" => [0x02190], "larrb" => [0x021E4], "larrbfs" => [0x0291F], "larrfs" => [0x0291D], "larrhk" => [0x021A9], "larrlp" => [0x021AB], "larrpl" => [0x02939], "larrsim" => [0x02973], "larrtl" => [0x021A2], "lat" => [0x02AAB], "latail" => [0x02919], "late" => [0x02AAD], "lates" => [0x02AAD, 0x0FE00], "lbarr" => [0x0290C], "lbbrk" => [0x02772], "lbrace" => [0x0007B], "lbrack" => [0x0005B], "lbrke" => [0x0298B], "lbrksld" => [0x0298F], "lbrkslu" => [0x0298D], "lcaron" => [0x0013E], "lcedil" => [0x0013C], "lceil" => [0x02308], "lcub" => [0x0007B], "lcy" => [0x0043B], "ldca" => [0x02936], "ldquo" => [0x0201C], "ldquor" => [0x0201E], "ldrdhar" => [0x02967], "ldrushar" => [0x0294B], "ldsh" => [0x021B2], "le" => [0x02264], "leftarrow" => [0x02190], "leftarrowtail" => [0x021A2], "leftharpoondown" => [0x021BD], "leftharpoonup" => [0x021BC], "leftleftarrows" => [0x021C7], "leftrightarrow" => [0x02194], "leftrightarrows" => [0x021C6], "leftrightharpoons" => [0x021CB], "leftrightsquigarrow" => [0x021AD], "leftthreetimes" => [0x022CB], "leg" => [0x022DA], "leq" => [0x02264], "leqq" => [0x02266], "leqslant" => [0x02A7D], "les" => [0x02A7D], "lescc" => [0x02AA8], "lesdot" => [0x02A7F], "lesdoto" => [0x02A81], "lesdotor" => [0x02A83], "lesg" => [0x022DA, 0x0FE00], "lesges" => [0x02A93], "lessapprox" => [0x02A85], "lessdot" => [0x022D6], "lesseqgtr" => [0x022DA], "lesseqqgtr" => [0x02A8B], "lessgtr" => [0x02276], "lesssim" => [0x02272], "lfisht" => [0x0297C], "lfloor" => [0x0230A], "lfr" => [0x1D529], "lg" => [0x02276], "lgE" => [0x02A91], "lhard" => [0x021BD], "lharu" => [0x021BC], "lharul" => [0x0296A], "lhblk" => [0x02584], "ljcy" => [0x00459], "ll" => [0x0226A], "llarr" => [0x021C7], "llcorner" => [0x0231E], "llhard" => [0x0296B], "lltri" => [0x025FA], "lmidot" => [0x00140], "lmoust" => [0x023B0], "lmoustache" => [0x023B0], "lnE" => [0x02268], "lnap" => [0x02A89], "lnapprox" => [0x02A89], "lne" => [0x02A87], "lneq" => [0x02A87], "lneqq" => [0x02268], "lnsim" => [0x022E6], "loang" => [0x027EC], "loarr" => [0x021FD], "lobrk" => [0x027E6], "longleftarrow" => [0x027F5], "longleftrightarrow" => [0x027F7], "longmapsto" => [0x027FC], "longrightarrow" => [0x027F6], "looparrowleft" => [0x021AB], "looparrowright" => [0x021AC], "lopar" => [0x02985], "lopf" => [0x1D55D], "loplus" => [0x02A2D], "lotimes" => [0x02A34], "lowast" => [0x02217], "lowbar" => [0x0005F], "loz" => [0x025CA], "lozenge" => [0x025CA], "lozf" => [0x029EB], "lpar" => [0x00028], "lparlt" => [0x02993], "lrarr" => [0x021C6], "lrcorner" => [0x0231F], "lrhar" => [0x021CB], "lrhard" => [0x0296D], "lrm" => [0x0200E], "lrtri" => [0x022BF], "lsaquo" => [0x02039], "lscr" => [0x1D4C1], "lsh" => [0x021B0], "lsim" => [0x02272], "lsime" => [0x02A8D], "lsimg" => [0x02A8F], "lsqb" => [0x0005B], "lsquo" => [0x02018], "lsquor" => [0x0201A], "lstrok" => [0x00142], "lt" => [0x0003C], "ltcc" => [0x02AA6], "ltcir" => [0x02A79], "ltdot" => [0x022D6], "lthree" => [0x022CB], "ltimes" => [0x022C9], "ltlarr" => [0x02976], "ltquest" => [0x02A7B], "ltrPar" => [0x02996], "ltri" => [0x025C3], "ltrie" => [0x022B4], "ltrif" => [0x025C2], "lurdshar" => [0x0294A], "luruhar" => [0x02966], "lvertneqq" => [0x02268, 0x0FE00], "lvnE" => [0x02268, 0x0FE00], "mDDot" => [0x0223A], "macr" => [0x000AF], "male" => [0x02642], "malt" => [0x02720], "maltese" => [0x02720], "map" => [0x021A6], "mapsto" => [0x021A6], "mapstodown" => [0x021A7], "mapstoleft" => [0x021A4], "mapstoup" => [0x021A5], "marker" => [0x025AE], "mcomma" => [0x02A29], "mcy" => [0x0043C], "mdash" => [0x02014], "measuredangle" => [0x02221], "mfr" => [0x1D52A], "mho" => [0x02127], "micro" => [0x000B5], "mid" => [0x02223], "midast" => [0x0002A], "midcir" => [0x02AF0], "middot" => [0x000B7], "minus" => [0x02212], "minusb" => [0x0229F], "minusd" => [0x02238], "minusdu" => [0x02A2A], "mlcp" => [0x02ADB], "mldr" => [0x02026], "mnplus" => [0x02213], "models" => [0x022A7], "mopf" => [0x1D55E], "mp" => [0x02213], "mscr" => [0x1D4C2], "mstpos" => [0x0223E], "mu" => [0x003BC], "multimap" => [0x022B8], "mumap" => [0x022B8], "nGg" => [0x022D9, 0x00338], "nGt" => [0x0226B, 0x020D2], "nGtv" => [0x0226B, 0x00338], "nLeftarrow" => [0x021CD], "nLeftrightarrow" => [0x021CE], "nLl" => [0x022D8, 0x00338], "nLt" => [0x0226A, 0x020D2], "nLtv" => [0x0226A, 0x00338], "nRightarrow" => [0x021CF], "nVDash" => [0x022AF], "nVdash" => [0x022AE], "nabla" => [0x02207], "nacute" => [0x00144], "nang" => [0x02220, 0x020D2], "nap" => [0x02249], "napE" => [0x02A70, 0x00338], "napid" => [0x0224B, 0x00338], "napos" => [0x00149], "napprox" => [0x02249], "natur" => [0x0266E], "natural" => [0x0266E], "naturals" => [0x02115], "nbsp" => [0x000A0], "nbump" => [0x0224E, 0x00338], "nbumpe" => [0x0224F, 0x00338], "ncap" => [0x02A43], "ncaron" => [0x00148], "ncedil" => [0x00146], "ncong" => [0x02247], "ncongdot" => [0x02A6D, 0x00338], "ncup" => [0x02A42], "ncy" => [0x0043D], "ndash" => [0x02013], "ne" => [0x02260], "neArr" => [0x021D7], "nearhk" => [0x02924], "nearr" => [0x02197], "nearrow" => [0x02197], "nedot" => [0x02250, 0x00338], "nequiv" => [0x02262], "nesear" => [0x02928], "nesim" => [0x02242, 0x00338], "nexist" => [0x02204], "nexists" => [0x02204], "nfr" => [0x1D52B], "ngE" => [0x02267, 0x00338], "nge" => [0x02271], "ngeq" => [0x02271], "ngeqq" => [0x02267, 0x00338], "ngeqslant" => [0x02A7E, 0x00338], "nges" => [0x02A7E, 0x00338], "ngsim" => [0x02275], "ngt" => [0x0226F], "ngtr" => [0x0226F], "nhArr" => [0x021CE], "nharr" => [0x021AE], "nhpar" => [0x02AF2], "ni" => [0x0220B], "nis" => [0x022FC], "nisd" => [0x022FA], "niv" => [0x0220B], "njcy" => [0x0045A], "nlArr" => [0x021CD], "nlE" => [0x02266, 0x00338], "nlarr" => [0x0219A], "nldr" => [0x02025], "nle" => [0x02270], "nleftarrow" => [0x0219A], "nleftrightarrow" => [0x021AE], "nleq" => [0x02270], "nleqq" => [0x02266, 0x00338], "nleqslant" => [0x02A7D, 0x00338], "nles" => [0x02A7D, 0x00338], "nless" => [0x0226E], "nlsim" => [0x02274], "nlt" => [0x0226E], "nltri" => [0x022EA], "nltrie" => [0x022EC], "nmid" => [0x02224], "nopf" => [0x1D55F], "not" => [0x000AC], "notin" => [0x02209], "notinE" => [0x022F9, 0x00338], "notindot" => [0x022F5, 0x00338], "notinva" => [0x02209], "notinvb" => [0x022F7], "notinvc" => [0x022F6], "notni" => [0x0220C], "notniva" => [0x0220C], "notnivb" => [0x022FE], "notnivc" => [0x022FD], "npar" => [0x02226], "nparallel" => [0x02226], "nparsl" => [0x02AFD, 0x020E5], "npart" => [0x02202, 0x00338], "npolint" => [0x02A14], "npr" => [0x02280], "nprcue" => [0x022E0], "npre" => [0x02AAF, 0x00338], "nprec" => [0x02280], "npreceq" => [0x02AAF, 0x00338], "nrArr" => [0x021CF], "nrarr" => [0x0219B], "nrarrc" => [0x02933, 0x00338], "nrarrw" => [0x0219D, 0x00338], "nrightarrow" => [0x0219B], "nrtri" => [0x022EB], "nrtrie" => [0x022ED], "nsc" => [0x02281], "nsccue" => [0x022E1], "nsce" => [0x02AB0, 0x00338], "nscr" => [0x1D4C3], "nshortmid" => [0x02224], "nshortparallel" => [0x02226], "nsim" => [0x02241], "nsime" => [0x02244], "nsimeq" => [0x02244], "nsmid" => [0x02224], "nspar" => [0x02226], "nsqsube" => [0x022E2], "nsqsupe" => [0x022E3], "nsub" => [0x02284], "nsubE" => [0x02AC5, 0x00338], "nsube" => [0x02288], "nsubset" => [0x02282, 0x020D2], "nsubseteq" => [0x02288], "nsubseteqq" => [0x02AC5, 0x00338], "nsucc" => [0x02281], "nsucceq" => [0x02AB0, 0x00338], "nsup" => [0x02285], "nsupE" => [0x02AC6, 0x00338], "nsupe" => [0x02289], "nsupset" => [0x02283, 0x020D2], "nsupseteq" => [0x02289], "nsupseteqq" => [0x02AC6, 0x00338], "ntgl" => [0x02279], "ntilde" => [0x000F1], "ntlg" => [0x02278], "ntriangleleft" => [0x022EA], "ntrianglelefteq" => [0x022EC], "ntriangleright" => [0x022EB], "ntrianglerighteq" => [0x022ED], "nu" => [0x003BD], "num" => [0x00023], "numero" => [0x02116], "numsp" => [0x02007], "nvDash" => [0x022AD], "nvHarr" => [0x02904], "nvap" => [0x0224D, 0x020D2], "nvdash" => [0x022AC], "nvge" => [0x02265, 0x020D2], "nvgt" => [0x0003E, 0x020D2], "nvinfin" => [0x029DE], "nvlArr" => [0x02902], "nvle" => [0x02264, 0x020D2], "nvlt" => [0x0003C, 0x020D2], "nvltrie" => [0x022B4, 0x020D2], "nvrArr" => [0x02903], "nvrtrie" => [0x022B5, 0x020D2], "nvsim" => [0x0223C, 0x020D2], "nwArr" => [0x021D6], "nwarhk" => [0x02923], "nwarr" => [0x02196], "nwarrow" => [0x02196], "nwnear" => [0x02927], "oS" => [0x024C8], "oacute" => [0x000F3], "oast" => [0x0229B], "ocir" => [0x0229A], "ocirc" => [0x000F4], "ocy" => [0x0043E], "odash" => [0x0229D], "odblac" => [0x00151], "odiv" => [0x02A38], "odot" => [0x02299], "odsold" => [0x029BC], "oelig" => [0x00153], "ofcir" => [0x029BF], "ofr" => [0x1D52C], "ogon" => [0x002DB], "ograve" => [0x000F2], "ogt" => [0x029C1], "ohbar" => [0x029B5], "ohm" => [0x003A9], "oint" => [0x0222E], "olarr" => [0x021BA], "olcir" => [0x029BE], "olcross" => [0x029BB], "oline" => [0x0203E], "olt" => [0x029C0], "omacr" => [0x0014D], "omega" => [0x003C9], "omicron" => [0x003BF], "omid" => [0x029B6], "ominus" => [0x02296], "oopf" => [0x1D560], "opar" => [0x029B7], "operp" => [0x029B9], "oplus" => [0x02295], "or" => [0x02228], "orarr" => [0x021BB], "ord" => [0x02A5D], "order" => [0x02134], "orderof" => [0x02134], "ordf" => [0x000AA], "ordm" => [0x000BA], "origof" => [0x022B6], "oror" => [0x02A56], "orslope" => [0x02A57], "orv" => [0x02A5B], "oscr" => [0x02134], "oslash" => [0x000F8], "osol" => [0x02298], "otilde" => [0x000F5], "otimes" => [0x02297], "otimesas" => [0x02A36], "ouml" => [0x000F6], "ovbar" => [0x0233D], "par" => [0x02225], "para" => [0x000B6], "parallel" => [0x02225], "parsim" => [0x02AF3], "parsl" => [0x02AFD], "part" => [0x02202], "pcy" => [0x0043F], "percnt" => [0x00025], "period" => [0x0002E], "permil" => [0x02030], "perp" => [0x022A5], "pertenk" => [0x02031], "pfr" => [0x1D52D], "phi" => [0x003C6], "phiv" => [0x003D5], "phmmat" => [0x02133], "phone" => [0x0260E], "pi" => [0x003C0], "pitchfork" => [0x022D4], "piv" => [0x003D6], "planck" => [0x0210F], "planckh" => [0x0210E], "plankv" => [0x0210F], "plus" => [0x0002B], "plusacir" => [0x02A23], "plusb" => [0x0229E], "pluscir" => [0x02A22], "plusdo" => [0x02214], "plusdu" => [0x02A25], "pluse" => [0x02A72], "plusmn" => [0x000B1], "plussim" => [0x02A26], "plustwo" => [0x02A27], "pm" => [0x000B1], "pointint" => [0x02A15], "popf" => [0x1D561], "pound" => [0x000A3], "pr" => [0x0227A], "prE" => [0x02AB3], "prap" => [0x02AB7], "prcue" => [0x0227C], "pre" => [0x02AAF], "prec" => [0x0227A], "precapprox" => [0x02AB7], "preccurlyeq" => [0x0227C], "preceq" => [0x02AAF], "precnapprox" => [0x02AB9], "precneqq" => [0x02AB5], "precnsim" => [0x022E8], "precsim" => [0x0227E], "prime" => [0x02032], "primes" => [0x02119], "prnE" => [0x02AB5], "prnap" => [0x02AB9], "prnsim" => [0x022E8], "prod" => [0x0220F], "profalar" => [0x0232E], "profline" => [0x02312], "profsurf" => [0x02313], "prop" => [0x0221D], "propto" => [0x0221D], "prsim" => [0x0227E], "prurel" => [0x022B0], "pscr" => [0x1D4C5], "psi" => [0x003C8], "puncsp" => [0x02008], "qfr" => [0x1D52E], "qint" => [0x02A0C], "qopf" => [0x1D562], "qprime" => [0x02057], "qscr" => [0x1D4C6], "quaternions" => [0x0210D], "quatint" => [0x02A16], "quest" => [0x0003F], "questeq" => [0x0225F], "quot" => [0x00022], "rAarr" => [0x021DB], "rArr" => [0x021D2], "rAtail" => [0x0291C], "rBarr" => [0x0290F], "rHar" => [0x02964], "race" => [0x0223D, 0x00331], "racute" => [0x00155], "radic" => [0x0221A], "raemptyv" => [0x029B3], "rang" => [0x027E9], "rangd" => [0x02992], "range" => [0x029A5], "rangle" => [0x027E9], "raquo" => [0x000BB], "rarr" => [0x02192], "rarrap" => [0x02975], "rarrb" => [0x021E5], "rarrbfs" => [0x02920], "rarrc" => [0x02933], "rarrfs" => [0x0291E], "rarrhk" => [0x021AA], "rarrlp" => [0x021AC], "rarrpl" => [0x02945], "rarrsim" => [0x02974], "rarrtl" => [0x021A3], "rarrw" => [0x0219D], "ratail" => [0x0291A], "ratio" => [0x02236], "rationals" => [0x0211A], "rbarr" => [0x0290D], "rbbrk" => [0x02773], "rbrace" => [0x0007D], "rbrack" => [0x0005D], "rbrke" => [0x0298C], "rbrksld" => [0x0298E], "rbrkslu" => [0x02990], "rcaron" => [0x00159], "rcedil" => [0x00157], "rceil" => [0x02309], "rcub" => [0x0007D], "rcy" => [0x00440], "rdca" => [0x02937], "rdldhar" => [0x02969], "rdquo" => [0x0201D], "rdquor" => [0x0201D], "rdsh" => [0x021B3], "real" => [0x0211C], "realine" => [0x0211B], "realpart" => [0x0211C], "reals" => [0x0211D], "rect" => [0x025AD], "reg" => [0x000AE], "rfisht" => [0x0297D], "rfloor" => [0x0230B], "rfr" => [0x1D52F], "rhard" => [0x021C1], "rharu" => [0x021C0], "rharul" => [0x0296C], "rho" => [0x003C1], "rhov" => [0x003F1], "rightarrow" => [0x02192], "rightarrowtail" => [0x021A3], "rightharpoondown" => [0x021C1], "rightharpoonup" => [0x021C0], "rightleftarrows" => [0x021C4], "rightleftharpoons" => [0x021CC], "rightrightarrows" => [0x021C9], "rightsquigarrow" => [0x0219D], "rightthreetimes" => [0x022CC], "ring" => [0x002DA], "risingdotseq" => [0x02253], "rlarr" => [0x021C4], "rlhar" => [0x021CC], "rlm" => [0x0200F], "rmoust" => [0x023B1], "rmoustache" => [0x023B1], "rnmid" => [0x02AEE], "roang" => [0x027ED], "roarr" => [0x021FE], "robrk" => [0x027E7], "ropar" => [0x02986], "ropf" => [0x1D563], "roplus" => [0x02A2E], "rotimes" => [0x02A35], "rpar" => [0x00029], "rpargt" => [0x02994], "rppolint" => [0x02A12], "rrarr" => [0x021C9], "rsaquo" => [0x0203A], "rscr" => [0x1D4C7], "rsh" => [0x021B1], "rsqb" => [0x0005D], "rsquo" => [0x02019], "rsquor" => [0x02019], "rthree" => [0x022CC], "rtimes" => [0x022CA], "rtri" => [0x025B9], "rtrie" => [0x022B5], "rtrif" => [0x025B8], "rtriltri" => [0x029CE], "ruluhar" => [0x02968], "rx" => [0x0211E], "sacute" => [0x0015B], "sbquo" => [0x0201A], "sc" => [0x0227B], "scE" => [0x02AB4], "scap" => [0x02AB8], "scaron" => [0x00161], "sccue" => [0x0227D], "sce" => [0x02AB0], "scedil" => [0x0015F], "scirc" => [0x0015D], "scnE" => [0x02AB6], "scnap" => [0x02ABA], "scnsim" => [0x022E9], "scpolint" => [0x02A13], "scsim" => [0x0227F], "scy" => [0x00441], "sdot" => [0x022C5], "sdotb" => [0x022A1], "sdote" => [0x02A66], "seArr" => [0x021D8], "searhk" => [0x02925], "searr" => [0x02198], "searrow" => [0x02198], "sect" => [0x000A7], "semi" => [0x0003B], "seswar" => [0x02929], "setminus" => [0x02216], "setmn" => [0x02216], "sext" => [0x02736], "sfr" => [0x1D530], "sfrown" => [0x02322], "sharp" => [0x0266F], "shchcy" => [0x00449], "shcy" => [0x00448], "shortmid" => [0x02223], "shortparallel" => [0x02225], "shy" => [0x000AD], "sigma" => [0x003C3], "sigmaf" => [0x003C2], "sigmav" => [0x003C2], "sim" => [0x0223C], "simdot" => [0x02A6A], "sime" => [0x02243], "simeq" => [0x02243], "simg" => [0x02A9E], "simgE" => [0x02AA0], "siml" => [0x02A9D], "simlE" => [0x02A9F], "simne" => [0x02246], "simplus" => [0x02A24], "simrarr" => [0x02972], "slarr" => [0x02190], "smallsetminus" => [0x02216], "smashp" => [0x02A33], "smeparsl" => [0x029E4], "smid" => [0x02223], "smile" => [0x02323], "smt" => [0x02AAA], "smte" => [0x02AAC], "smtes" => [0x02AAC, 0x0FE00], "softcy" => [0x0044C], "sol" => [0x0002F], "solb" => [0x029C4], "solbar" => [0x0233F], "sopf" => [0x1D564], "spades" => [0x02660], "spadesuit" => [0x02660], "spar" => [0x02225], "sqcap" => [0x02293], "sqcaps" => [0x02293, 0x0FE00], "sqcup" => [0x02294], "sqcups" => [0x02294, 0x0FE00], "sqsub" => [0x0228F], "sqsube" => [0x02291], "sqsubset" => [0x0228F], "sqsubseteq" => [0x02291], "sqsup" => [0x02290], "sqsupe" => [0x02292], "sqsupset" => [0x02290], "sqsupseteq" => [0x02292], "squ" => [0x025A1], "square" => [0x025A1], "squarf" => [0x025AA], "squf" => [0x025AA], "srarr" => [0x02192], "sscr" => [0x1D4C8], "ssetmn" => [0x02216], "ssmile" => [0x02323], "sstarf" => [0x022C6], "star" => [0x02606], "starf" => [0x02605], "straightepsilon" => [0x003F5], "straightphi" => [0x003D5], "strns" => [0x000AF], "sub" => [0x02282], "subE" => [0x02AC5], "subdot" => [0x02ABD], "sube" => [0x02286], "subedot" => [0x02AC3], "submult" => [0x02AC1], "subnE" => [0x02ACB], "subne" => [0x0228A], "subplus" => [0x02ABF], "subrarr" => [0x02979], "subset" => [0x02282], "subseteq" => [0x02286], "subseteqq" => [0x02AC5], "subsetneq" => [0x0228A], "subsetneqq" => [0x02ACB], "subsim" => [0x02AC7], "subsub" => [0x02AD5], "subsup" => [0x02AD3], "succ" => [0x0227B], "succapprox" => [0x02AB8], "succcurlyeq" => [0x0227D], "succeq" => [0x02AB0], "succnapprox" => [0x02ABA], "succneqq" => [0x02AB6], "succnsim" => [0x022E9], "succsim" => [0x0227F], "sum" => [0x02211], "sung" => [0x0266A], "sup" => [0x02283], "sup1" => [0x000B9], "sup2" => [0x000B2], "sup3" => [0x000B3], "supE" => [0x02AC6], "supdot" => [0x02ABE], "supdsub" => [0x02AD8], "supe" => [0x02287], "supedot" => [0x02AC4], "suphsol" => [0x027C9], "suphsub" => [0x02AD7], "suplarr" => [0x0297B], "supmult" => [0x02AC2], "supnE" => [0x02ACC], "supne" => [0x0228B], "supplus" => [0x02AC0], "supset" => [0x02283], "supseteq" => [0x02287], "supseteqq" => [0x02AC6], "supsetneq" => [0x0228B], "supsetneqq" => [0x02ACC], "supsim" => [0x02AC8], "supsub" => [0x02AD4], "supsup" => [0x02AD6], "swArr" => [0x021D9], "swarhk" => [0x02926], "swarr" => [0x02199], "swarrow" => [0x02199], "swnwar" => [0x0292A], "szlig" => [0x000DF], "target" => [0x02316], "tau" => [0x003C4], "tbrk" => [0x023B4], "tcaron" => [0x00165], "tcedil" => [0x00163], "tcy" => [0x00442], "tdot" => [0x020DB], "telrec" => [0x02315], "tfr" => [0x1D531], "there4" => [0x02234], "therefore" => [0x02234], "theta" => [0x003B8], "thetasym" => [0x003D1], "thetav" => [0x003D1], "thickapprox" => [0x02248], "thicksim" => [0x0223C], "thinsp" => [0x02009], "thkap" => [0x02248], "thksim" => [0x0223C], "thorn" => [0x000FE], "tilde" => [0x002DC], "times" => [0x000D7], "timesb" => [0x022A0], "timesbar" => [0x02A31], "timesd" => [0x02A30], "tint" => [0x0222D], "toea" => [0x02928], "top" => [0x022A4], "topbot" => [0x02336], "topcir" => [0x02AF1], "topf" => [0x1D565], "topfork" => [0x02ADA], "tosa" => [0x02929], "tprime" => [0x02034], "trade" => [0x02122], "triangle" => [0x025B5], "triangledown" => [0x025BF], "triangleleft" => [0x025C3], "trianglelefteq" => [0x022B4], "triangleq" => [0x0225C], "triangleright" => [0x025B9], "trianglerighteq" => [0x022B5], "tridot" => [0x025EC], "trie" => [0x0225C], "triminus" => [0x02A3A], "triplus" => [0x02A39], "trisb" => [0x029CD], "tritime" => [0x02A3B], "trpezium" => [0x023E2], "tscr" => [0x1D4C9], "tscy" => [0x00446], "tshcy" => [0x0045B], "tstrok" => [0x00167], "twixt" => [0x0226C], "twoheadleftarrow" => [0x0219E], "twoheadrightarrow" => [0x021A0], "uArr" => [0x021D1], "uHar" => [0x02963], "uacute" => [0x000FA], "uarr" => [0x02191], "ubrcy" => [0x0045E], "ubreve" => [0x0016D], "ucirc" => [0x000FB], "ucy" => [0x00443], "udarr" => [0x021C5], "udblac" => [0x00171], "udhar" => [0x0296E], "ufisht" => [0x0297E], "ufr" => [0x1D532], "ugrave" => [0x000F9], "uharl" => [0x021BF], "uharr" => [0x021BE], "uhblk" => [0x02580], "ulcorn" => [0x0231C], "ulcorner" => [0x0231C], "ulcrop" => [0x0230F], "ultri" => [0x025F8], "umacr" => [0x0016B], "uml" => [0x000A8], "uogon" => [0x00173], "uopf" => [0x1D566], "uparrow" => [0x02191], "updownarrow" => [0x02195], "upharpoonleft" => [0x021BF], "upharpoonright" => [0x021BE], "uplus" => [0x0228E], "upsi" => [0x003C5], "upsih" => [0x003D2], "upsilon" => [0x003C5], "upuparrows" => [0x021C8], "urcorn" => [0x0231D], "urcorner" => [0x0231D], "urcrop" => [0x0230E], "uring" => [0x0016F], "urtri" => [0x025F9], "uscr" => [0x1D4CA], "utdot" => [0x022F0], "utilde" => [0x00169], "utri" => [0x025B5], "utrif" => [0x025B4], "uuarr" => [0x021C8], "uuml" => [0x000FC], "uwangle" => [0x029A7], "vArr" => [0x021D5], "vBar" => [0x02AE8], "vBarv" => [0x02AE9], "vDash" => [0x022A8], "vangrt" => [0x0299C], "varepsilon" => [0x003F5], "varkappa" => [0x003F0], "varnothing" => [0x02205], "varphi" => [0x003D5], "varpi" => [0x003D6], "varpropto" => [0x0221D], "varr" => [0x02195], "varrho" => [0x003F1], "varsigma" => [0x003C2], "varsubsetneq" => [0x0228A, 0x0FE00], "varsubsetneqq" => [0x02ACB, 0x0FE00], "varsupsetneq" => [0x0228B, 0x0FE00], "varsupsetneqq" => [0x02ACC, 0x0FE00], "vartheta" => [0x003D1], "vartriangleleft" => [0x022B2], "vartriangleright" => [0x022B3], "vcy" => [0x00432], "vdash" => [0x022A2], "vee" => [0x02228], "veebar" => [0x022BB], "veeeq" => [0x0225A], "vellip" => [0x022EE], "verbar" => [0x0007C], "vert" => [0x0007C], "vfr" => [0x1D533], "vltri" => [0x022B2], "vnsub" => [0x02282, 0x020D2], "vnsup" => [0x02283, 0x020D2], "vopf" => [0x1D567], "vprop" => [0x0221D], "vrtri" => [0x022B3], "vscr" => [0x1D4CB], "vsubnE" => [0x02ACB, 0x0FE00], "vsubne" => [0x0228A, 0x0FE00], "vsupnE" => [0x02ACC, 0x0FE00], "vsupne" => [0x0228B, 0x0FE00], "vzigzag" => [0x0299A], "wcirc" => [0x00175], "wedbar" => [0x02A5F], "wedge" => [0x02227], "wedgeq" => [0x02259], "weierp" => [0x02118], "wfr" => [0x1D534], "wopf" => [0x1D568], "wp" => [0x02118], "wr" => [0x02240], "wreath" => [0x02240], "wscr" => [0x1D4CC], "xcap" => [0x022C2], "xcirc" => [0x025EF], "xcup" => [0x022C3], "xdtri" => [0x025BD], "xfr" => [0x1D535], "xhArr" => [0x027FA], "xharr" => [0x027F7], "xi" => [0x003BE], "xlArr" => [0x027F8], "xlarr" => [0x027F5], "xmap" => [0x027FC], "xnis" => [0x022FB], "xodot" => [0x02A00], "xopf" => [0x1D569], "xoplus" => [0x02A01], "xotime" => [0x02A02], "xrArr" => [0x027F9], "xrarr" => [0x027F6], "xscr" => [0x1D4CD], "xsqcup" => [0x02A06], "xuplus" => [0x02A04], "xutri" => [0x025B3], "xvee" => [0x022C1], "xwedge" => [0x022C0], "yacute" => [0x000FD], "yacy" => [0x0044F], "ycirc" => [0x00177], "ycy" => [0x0044B], "yen" => [0x000A5], "yfr" => [0x1D536], "yicy" => [0x00457], "yopf" => [0x1D56A], "yscr" => [0x1D4CE], "yucy" => [0x0044E], "yuml" => [0x000FF], "zacute" => [0x0017A], "zcaron" => [0x0017E], "zcy" => [0x00437], "zdot" => [0x0017C], "zeetrf" => [0x02128], "zeta" => [0x003B6], "zfr" => [0x1D537], "zhcy" => [0x00436], "zigrarr" => [0x021DD], "zopf" => [0x1D56B], "zscr" => [0x1D4CF], "zwj" => [0x0200D], "zwnj" => [0x0200C], } rdoc/extend.rb000064400000005032147635155430007324 0ustar00## # A Module extension in a class with \#extend class RDoc::Extend < RDoc::CodeObject ## # Name of extension module attr_accessor :name ## # Creates a new Extend for +name+ with +comment+ def initialize(name, comment) super() @name = name self.comment = comment @module = nil # cache for module if found end ## # Extends are sorted by name def <=> other return unless self.class === other name <=> other.name end def == other # :nodoc: self.class === other and @name == other.name end alias eql? == ## # Full name based on #module def full_name m = self.module RDoc::ClassModule === m ? m.full_name : @name end def hash # :nodoc: [@name, self.module].hash end def inspect # :nodoc: "#<%s:0x%x %s.extend %s>" % [ self.class, object_id, parent_name, @name, ] end ## # Attempts to locate the extend module object. Returns the name if not # known. # # The scoping rules of Ruby to resolve the name of an extension module are: # - first look into the children of the current context; # - if not found, look into the children of extension modules, # in reverse extend order; # - if still not found, go up the hierarchy of names. # # This method has O(n!) behavior when the module calling # extend is referencing nonexistent modules. Avoid calling #module until # after all the files are parsed. This behavior is due to ruby's constant # lookup behavior. def module return @module if @module # search the current context return @name unless parent full_name = parent.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module return @name if @name =~ /^::/ # search the includes before this one, in reverse order searched = parent.extends.take_while { |i| i != self }.reverse searched.each do |i| ext = i.module next if String === ext full_name = ext.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module end # go up the hierarchy of names up = parent.parent while up full_name = up.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module up = up.parent end @name end ## # Sets the store for this class or module and its contained code objects. def store= store super @file = @store.add_file @file.full_name if @file end def to_s # :nodoc: "extend #@name in: #{parent}" end end rdoc/stats.rb000064400000023443147635155430007201 0ustar00## # RDoc statistics collector which prints a summary and report of a project's # documentation totals. class RDoc::Stats ## # Output level for the coverage report attr_reader :coverage_level ## # Count of files parsed during parsing attr_reader :files_so_far ## # Total number of files found attr_reader :num_files ## # Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1 # which will create an RDoc::Stats::Normal outputter. def initialize store, num_files, verbosity = 1 @num_files = num_files @store = store @coverage_level = 0 @doc_items = nil @files_so_far = 0 @fully_documented = false @num_params = 0 @percent_doc = nil @start = Time.now @undoc_params = 0 @display = case verbosity when 0 then Quiet.new num_files when 1 then Normal.new num_files else Verbose.new num_files end end ## # Records the parsing of an alias +as+. def add_alias as @display.print_alias as end ## # Records the parsing of an attribute +attribute+ def add_attribute attribute @display.print_attribute attribute end ## # Records the parsing of a class +klass+ def add_class klass @display.print_class klass end ## # Records the parsing of +constant+ def add_constant constant @display.print_constant constant end ## # Records the parsing of +file+ def add_file(file) @files_so_far += 1 @display.print_file @files_so_far, file end ## # Records the parsing of +method+ def add_method(method) @display.print_method method end ## # Records the parsing of a module +mod+ def add_module(mod) @display.print_module mod end ## # Call this to mark the beginning of parsing for display purposes def begin_adding @display.begin_adding end ## # Calculates documentation totals and percentages for classes, modules, # constants, attributes and methods. def calculate return if @doc_items ucm = @store.unique_classes_and_modules classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' } constants = [] ucm.each { |cm| constants.concat cm.constants } methods = [] ucm.each { |cm| methods.concat cm.method_list } attributes = [] ucm.each { |cm| attributes.concat cm.attributes } @num_attributes, @undoc_attributes = doc_stats attributes @num_classes, @undoc_classes = doc_stats classes @num_constants, @undoc_constants = doc_stats constants @num_methods, @undoc_methods = doc_stats methods @num_modules, @undoc_modules = doc_stats @store.unique_modules @num_items = @num_attributes + @num_classes + @num_constants + @num_methods + @num_modules + @num_params @undoc_items = @undoc_attributes + @undoc_classes + @undoc_constants + @undoc_methods + @undoc_modules + @undoc_params @doc_items = @num_items - @undoc_items end ## # Sets coverage report level. Accepted values are: # # false or nil:: No report # 0:: Classes, modules, constants, attributes, methods # 1:: Level 0 + method parameters def coverage_level= level level = -1 unless level @coverage_level = level end ## # Returns the length and number of undocumented items in +collection+. def doc_stats collection visible = collection.select { |item| item.display? } [visible.length, visible.count { |item| not item.documented? }] end ## # Call this to mark the end of parsing for display purposes def done_adding @display.done_adding end ## # The documentation status of this project. +true+ when 100%, +false+ when # less than 100% and +nil+ when unknown. # # Set by calling #calculate def fully_documented? @fully_documented end ## # A report that says you did a great job! def great_job report = [] report << '100% documentation!' report << nil report << 'Great Job!' report.join "\n" end ## # Calculates the percentage of items documented. def percent_doc return @percent_doc if @percent_doc @fully_documented = (@num_items - @doc_items) == 0 @percent_doc = @doc_items.to_f / @num_items * 100 if @num_items.nonzero? @percent_doc ||= 0 @percent_doc end ## # Returns a report on which items are not documented def report if @coverage_level > 0 then extend RDoc::Text end report = [] if @coverage_level.zero? then calculate return great_job if @num_items == @doc_items end ucm = @store.unique_classes_and_modules ucm.sort.each do |cm| report << report_class_module(cm) { [ report_constants(cm), report_attributes(cm), report_methods(cm), ].compact } end if @coverage_level > 0 then calculate return great_job if @num_items == @doc_items end report.unshift nil report.unshift 'The following items are not documented:' report.join "\n" end ## # Returns a report on undocumented attributes in ClassModule +cm+ def report_attributes cm return if cm.attributes.empty? report = [] cm.each_attribute do |attr| next if attr.documented? line = attr.line ? ":#{attr.line}" : nil report << " #{attr.definition} :#{attr.name} # in file #{attr.file.full_name}#{line}" end report end ## # Returns a report on undocumented items in ClassModule +cm+ def report_class_module cm return if cm.fully_documented? and @coverage_level.zero? return unless cm.display? report = [] if cm.in_files.empty? then report << "# #{cm.definition} is referenced but empty." report << "#" report << "# It probably came from another project. I'm sorry I'm holding it against you." report << nil return report elsif cm.documented? then documented = true report << "#{cm.definition} # is documented" else report << '# in files:' cm.in_files.each do |file| report << "# #{file.full_name}" end report << nil report << "#{cm.definition}" end body = yield.flatten # HACK remove #flatten return if body.empty? and documented report << nil << body unless body.empty? report << 'end' report << nil report end ## # Returns a report on undocumented constants in ClassModule +cm+ def report_constants cm return if cm.constants.empty? report = [] cm.each_constant do |constant| # TODO constant aliases are listed in the summary but not reported # figure out what to do here next if constant.documented? || constant.is_alias_for line = constant.line ? ":#{constant.line}" : line report << " # in file #{constant.file.full_name}#{line}" report << " #{constant.name} = nil" end report end ## # Returns a report on undocumented methods in ClassModule +cm+ def report_methods cm return if cm.method_list.empty? report = [] cm.each_method do |method| next if method.documented? and @coverage_level.zero? if @coverage_level > 0 then params, undoc = undoc_params method @num_params += params unless undoc.empty? then @undoc_params += undoc.length undoc = undoc.map do |param| "+#{param}+" end param_report = " # #{undoc.join ', '} is not documented" end end next if method.documented? and not param_report line = method.line ? ":#{method.line}" : nil scope = method.singleton ? 'self.' : nil report << " # in file #{method.file.full_name}#{line}" report << param_report if param_report report << " def #{scope}#{method.name}#{method.params}; end" report << nil end report end ## # Returns a summary of the collected statistics. def summary calculate num_width = [@num_files, @num_items].max.to_s.length undoc_width = [ @undoc_attributes, @undoc_classes, @undoc_constants, @undoc_items, @undoc_methods, @undoc_modules, @undoc_params, ].max.to_s.length report = [] report << 'Files: %*d' % [num_width, @num_files] report << nil report << 'Classes: %*d (%*d undocumented)' % [ num_width, @num_classes, undoc_width, @undoc_classes] report << 'Modules: %*d (%*d undocumented)' % [ num_width, @num_modules, undoc_width, @undoc_modules] report << 'Constants: %*d (%*d undocumented)' % [ num_width, @num_constants, undoc_width, @undoc_constants] report << 'Attributes: %*d (%*d undocumented)' % [ num_width, @num_attributes, undoc_width, @undoc_attributes] report << 'Methods: %*d (%*d undocumented)' % [ num_width, @num_methods, undoc_width, @undoc_methods] report << 'Parameters: %*d (%*d undocumented)' % [ num_width, @num_params, undoc_width, @undoc_params] if @coverage_level > 0 report << nil report << 'Total: %*d (%*d undocumented)' % [ num_width, @num_items, undoc_width, @undoc_items] report << '%6.2f%% documented' % percent_doc report << nil report << 'Elapsed: %0.1fs' % (Time.now - @start) report.join "\n" end ## # Determines which parameters in +method+ were not documented. Returns a # total parameter count and an Array of undocumented methods. def undoc_params method @formatter ||= RDoc::Markup::ToTtOnly.new params = method.param_list return 0, [] if params.empty? document = parse method.comment tts = document.accept @formatter undoc = params - tts [params.length, undoc] end autoload :Quiet, 'rdoc/stats/quiet' autoload :Normal, 'rdoc/stats/normal' autoload :Verbose, 'rdoc/stats/verbose' end rdoc/erb_partial.rb000064400000000562147635155430010324 0ustar00## # Allows an ERB template to be rendered in the context (binding) of an # existing ERB template evaluation. class RDoc::ERBPartial < ERB ## # Overrides +compiler+ startup to set the +eoutvar+ to an empty string only # if it isn't already set. def set_eoutvar compiler, eoutvar = '_erbout' super compiler.pre_cmd = ["#{eoutvar} ||= ''"] end end rdoc/include.rb000064400000005165147635155430007467 0ustar00## # A Module include in a class with \#include class RDoc::Include < RDoc::CodeObject ## # Name of included module attr_accessor :name ## # Creates a new Include for +name+ with +comment+ def initialize(name, comment) super() @name = name self.comment = comment @module = nil # cache for module if found end ## # Includes are sorted by name def <=> other return unless self.class === other name <=> other.name end def == other # :nodoc: self.class === other and @name == other.name end alias eql? == ## # Full name based on #module def full_name m = self.module RDoc::ClassModule === m ? m.full_name : @name end def hash # :nodoc: [@name, self.module].hash end def inspect # :nodoc: "#<%s:0x%x %s.include %s>" % [ self.class, object_id, parent_name, @name, ] end ## # Attempts to locate the included module object. Returns the name if not # known. # # The scoping rules of Ruby to resolve the name of an included module are: # - first look into the children of the current context; # - if not found, look into the children of included modules, # in reverse inclusion order; # - if still not found, go up the hierarchy of names. # # This method has O(n!) behavior when the module calling # include is referencing nonexistent modules. Avoid calling #module until # after all the files are parsed. This behavior is due to ruby's constant # lookup behavior. # # As of the beginning of October, 2011, no gem includes nonexistent modules. def module return @module if @module # search the current context return @name unless parent full_name = parent.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module return @name if @name =~ /^::/ # search the includes before this one, in reverse order searched = parent.includes.take_while { |i| i != self }.reverse searched.each do |i| inc = i.module next if String === inc full_name = inc.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module end # go up the hierarchy of names up = parent.parent while up full_name = up.child_name(@name) @module = @store.modules_hash[full_name] return @module if @module up = up.parent end @name end ## # Sets the store for this class or module and its contained code objects. def store= store super @file = @store.add_file @file.full_name if @file end def to_s # :nodoc: "include #@name in: #{parent}" end end rdoc.rb000064400000011602147635155430006035 0ustar00$DEBUG_RDOC = nil # :main: README.rdoc ## # RDoc produces documentation for Ruby source files by parsing the source and # extracting the definition for classes, modules, methods, includes and # requires. It associates these with optional documentation contained in an # immediately preceding comment block then renders the result using an output # formatter. # # For a simple introduction to writing or generating documentation using RDoc # see the README. # # == Roadmap # # If you think you found a bug in RDoc see DEVELOPERS@Bugs # # If you want to use RDoc to create documentation for your Ruby source files, # see RDoc::Markup and refer to rdoc --help for command line usage. # # If you want to set the default markup format see # RDoc::Markup@Supported+Formats # # If you want to store rdoc configuration in your gem (such as the default # markup format) see RDoc::Options@Saved+Options # # If you want to write documentation for Ruby files see RDoc::Parser::Ruby # # If you want to write documentation for extensions written in C see # RDoc::Parser::C # # If you want to generate documentation using rake see RDoc::Task. # # If you want to drive RDoc programmatically, see RDoc::RDoc. # # If you want to use the library to format text blocks into HTML or other # formats, look at RDoc::Markup. # # If you want to make an RDoc plugin such as a generator or directive handler # see RDoc::RDoc. # # If you want to write your own output generator see RDoc::Generator. # # If you want an overview of how RDoc works see DEVELOPERS # # == Credits # # RDoc is currently being maintained by Eric Hodel . # # Dave Thomas is the original author of RDoc. # # * The Ruby parser in rdoc/parse.rb is based heavily on the outstanding # work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby # parser for irb and the rtags package. module RDoc ## # Exception thrown by any rdoc error. class Error < RuntimeError; end ## # RDoc version you are using VERSION = '4.0.0' ## # Method visibilities VISIBILITIES = [:public, :protected, :private] ## # Name of the dotfile that contains the description of files to be processed # in the current directory DOT_DOC_FILENAME = ".document" ## # General RDoc modifiers GENERAL_MODIFIERS = %w[nodoc].freeze ## # RDoc modifiers for classes CLASS_MODIFIERS = GENERAL_MODIFIERS ## # RDoc modifiers for attributes ATTR_MODIFIERS = GENERAL_MODIFIERS ## # RDoc modifiers for constants CONSTANT_MODIFIERS = GENERAL_MODIFIERS ## # RDoc modifiers for methods METHOD_MODIFIERS = GENERAL_MODIFIERS + %w[arg args yield yields notnew not-new not_new doc] ## # Loads the best available YAML library. def self.load_yaml begin gem 'psych' rescue Gem::LoadError end begin require 'psych' rescue ::LoadError ensure require 'yaml' end end autoload :RDoc, 'rdoc/rdoc' autoload :TestCase, 'rdoc/test_case' autoload :CrossReference, 'rdoc/cross_reference' autoload :ERBIO, 'rdoc/erbio' autoload :ERBPartial, 'rdoc/erb_partial' autoload :Encoding, 'rdoc/encoding' autoload :Generator, 'rdoc/generator' autoload :Options, 'rdoc/options' autoload :Parser, 'rdoc/parser' autoload :Servlet, 'rdoc/servlet' autoload :RI, 'rdoc/ri' autoload :Stats, 'rdoc/stats' autoload :Store, 'rdoc/store' autoload :Task, 'rdoc/task' autoload :Text, 'rdoc/text' autoload :Markdown, 'rdoc/markdown' autoload :Markup, 'rdoc/markup' autoload :RD, 'rdoc/rd' autoload :TomDoc, 'rdoc/tom_doc' autoload :KNOWN_CLASSES, 'rdoc/known_classes' autoload :RubyLex, 'rdoc/ruby_lex' autoload :RubyToken, 'rdoc/ruby_token' autoload :TokenStream, 'rdoc/token_stream' autoload :Comment, 'rdoc/comment' # code objects # # We represent the various high-level code constructs that appear in Ruby # programs: classes, modules, methods, and so on. autoload :CodeObject, 'rdoc/code_object' autoload :Context, 'rdoc/context' autoload :TopLevel, 'rdoc/top_level' autoload :AnonClass, 'rdoc/anon_class' autoload :ClassModule, 'rdoc/class_module' autoload :NormalClass, 'rdoc/normal_class' autoload :NormalModule, 'rdoc/normal_module' autoload :SingleClass, 'rdoc/single_class' autoload :Alias, 'rdoc/alias' autoload :AnyMethod, 'rdoc/any_method' autoload :MethodAttr, 'rdoc/method_attr' autoload :GhostMethod, 'rdoc/ghost_method' autoload :MetaMethod, 'rdoc/meta_method' autoload :Attr, 'rdoc/attr' autoload :Constant, 'rdoc/constant' autoload :Include, 'rdoc/include' autoload :Extend, 'rdoc/extend' autoload :Require, 'rdoc/require' end io/console/size.rb000064400000000513147635166300010126 0ustar00def IO.default_console_size [ ENV["LINES"].to_i.nonzero? || 25, ENV["COLUMNS"].to_i.nonzero? || 80, ] end begin require 'io/console' rescue LoadError class IO alias console_size default_console_size end else def IO.console_size console.winsize rescue NoMethodError default_console_size end end json/common.rb000064400000037513147635506700007360 0ustar00require 'json/version' require 'json/generic_object' module JSON class << self # If _object_ is string-like, parse the string and return the parsed result # as a Ruby data structure. Otherwise generate a JSON text from the Ruby # data structure object and return it. # # The _opts_ argument is passed through to generate/parse respectively. See # generate and parse for their documentation. def [](object, opts = {}) if object.respond_to? :to_str JSON.parse(object.to_str, opts) else JSON.generate(object, opts) end end # Returns the JSON parser class that is used by JSON. This is either # JSON::Ext::Parser or JSON::Pure::Parser. attr_reader :parser # Set the JSON parser class _parser_ to be used by JSON. def parser=(parser) # :nodoc: @parser = parser remove_const :Parser if JSON.const_defined_in?(self, :Parser) const_set :Parser, parser end # Return the constant located at _path_. The format of _path_ has to be # either ::A::B::C or A::B::C. In any case, A has to be located at the top # level (absolute namespace path?). If there doesn't exist a constant at # the given path, an ArgumentError is raised. def deep_const_get(path) # :nodoc: path.to_s.split(/::/).inject(Object) do |p, c| case when c.empty? then p when JSON.const_defined_in?(p, c) then p.const_get(c) else begin p.const_missing(c) rescue NameError => e raise ArgumentError, "can't get const #{path}: #{e}" end end end end # Set the module _generator_ to be used by JSON. def generator=(generator) # :nodoc: old, $VERBOSE = $VERBOSE, nil @generator = generator generator_methods = generator::GeneratorMethods for const in generator_methods.constants klass = deep_const_get(const) modul = generator_methods.const_get(const) klass.class_eval do instance_methods(false).each do |m| m.to_s == 'to_json' and remove_method m end include modul end end self.state = generator::State const_set :State, self.state const_set :SAFE_STATE_PROTOTYPE, State.new const_set :FAST_STATE_PROTOTYPE, State.new( :indent => '', :space => '', :object_nl => "", :array_nl => "", :max_nesting => false ) const_set :PRETTY_STATE_PROTOTYPE, State.new( :indent => ' ', :space => ' ', :object_nl => "\n", :array_nl => "\n" ) ensure $VERBOSE = old end # Returns the JSON generator module that is used by JSON. This is # either JSON::Ext::Generator or JSON::Pure::Generator. attr_reader :generator # Returns the JSON generator state class that is used by JSON. This is # either JSON::Ext::Generator::State or JSON::Pure::Generator::State. attr_accessor :state # This is create identifier, which is used to decide if the _json_create_ # hook of a class should be called. It defaults to 'json_class'. attr_accessor :create_id end self.create_id = 'json_class' NaN = 0.0/0 Infinity = 1.0/0 MinusInfinity = -Infinity # The base exception for JSON errors. class JSONError < StandardError def self.wrap(exception) obj = new("Wrapped(#{exception.class}): #{exception.message.inspect}") obj.set_backtrace exception.backtrace obj end end # This exception is raised if a parser error occurs. class ParserError < JSONError; end # This exception is raised if the nesting of parsed data structures is too # deep. class NestingError < ParserError; end # :stopdoc: class CircularDatastructure < NestingError; end # :startdoc: # This exception is raised if a generator or unparser error occurs. class GeneratorError < JSONError; end # For backwards compatibility UnparserError = GeneratorError # This exception is raised if the required unicode support is missing on the # system. Usually this means that the iconv library is not installed. class MissingUnicodeSupport < JSONError; end module_function # Parse the JSON document _source_ into a Ruby data structure and return it. # # _opts_ can have the following # keys: # * *max_nesting*: The maximum depth of nesting allowed in the parsed data # structures. Disable depth checking with :max_nesting => false. It defaults # to 100. # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in # defiance of RFC 4627 to be parsed by the Parser. This option defaults # to false. # * *symbolize_names*: If set to true, returns symbols for the names # (keys) in a JSON object. Otherwise strings are returned. Strings are # the default. # * *create_additions*: If set to false, the Parser doesn't create # additions even if a matching class and create_id was found. This option # defaults to true. # * *object_class*: Defaults to Hash # * *array_class*: Defaults to Array def parse(source, opts = {}) Parser.new(source, opts).parse end # Parse the JSON document _source_ into a Ruby data structure and return it. # The bang version of the parse method defaults to the more dangerous values # for the _opts_ hash, so be sure only to parse trusted _source_ documents. # # _opts_ can have the following keys: # * *max_nesting*: The maximum depth of nesting allowed in the parsed data # structures. Enable depth checking with :max_nesting => anInteger. The parse! # methods defaults to not doing max depth checking: This can be dangerous # if someone wants to fill up your stack. # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in # defiance of RFC 4627 to be parsed by the Parser. This option defaults # to true. # * *create_additions*: If set to false, the Parser doesn't create # additions even if a matching class and create_id was found. This option # defaults to true. def parse!(source, opts = {}) opts = { :max_nesting => false, :allow_nan => true }.update(opts) Parser.new(source, opts).parse end # Generate a JSON document from the Ruby data structure _obj_ and return # it. _state_ is # * a JSON::State object, # * or a Hash like object (responding to to_hash), # * or an object convertible into a hash by a to_h method, # that is used as or to configure a State object. # # It defaults to a state object, that creates the shortest possible JSON text # in one line, checks for circular data structures and doesn't allow NaN, # Infinity, and -Infinity. # # A _state_ hash can have the following keys: # * *indent*: a string used to indent levels (default: ''), # * *space*: a string that is put after, a : or , delimiter (default: ''), # * *space_before*: a string that is put before a : pair delimiter (default: ''), # * *object_nl*: a string that is put at the end of a JSON object (default: ''), # * *array_nl*: a string that is put at the end of a JSON array (default: ''), # * *allow_nan*: true if NaN, Infinity, and -Infinity should be # generated, otherwise an exception is thrown if these values are # encountered. This options defaults to false. # * *max_nesting*: The maximum depth of nesting allowed in the data # structures from which JSON is to be generated. Disable depth checking # with :max_nesting => false, it defaults to 100. # # See also the fast_generate for the fastest creation method with the least # amount of sanity checks, and the pretty_generate method for some # defaults for pretty output. def generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = SAFE_STATE_PROTOTYPE.dup end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state = state.configure(opts) end state.generate(obj) end # :stopdoc: # I want to deprecate these later, so I'll first be silent about them, and # later delete them. alias unparse generate module_function :unparse # :startdoc: # Generate a JSON document from the Ruby data structure _obj_ and return it. # This method disables the checks for circles in Ruby objects. # # *WARNING*: Be careful not to pass any Ruby data structures with circles as # _obj_ argument because this will cause JSON to go into an infinite loop. def fast_generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = FAST_STATE_PROTOTYPE.dup end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state.configure(opts) end state.generate(obj) end # :stopdoc: # I want to deprecate these later, so I'll first be silent about them, and later delete them. alias fast_unparse fast_generate module_function :fast_unparse # :startdoc: # Generate a JSON document from the Ruby data structure _obj_ and return it. # The returned document is a prettier form of the document returned by # #unparse. # # The _opts_ argument can be used to configure the generator. See the # generate method for a more detailed explanation. def pretty_generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = PRETTY_STATE_PROTOTYPE.dup end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state.configure(opts) end state.generate(obj) end # :stopdoc: # I want to deprecate these later, so I'll first be silent about them, and later delete them. alias pretty_unparse pretty_generate module_function :pretty_unparse # :startdoc: class << self # The global default options for the JSON.load method: # :max_nesting: false # :allow_nan: true # :quirks_mode: true attr_accessor :load_default_options end self.load_default_options = { :max_nesting => false, :allow_nan => true, :quirks_mode => true, :create_additions => true, } # Load a ruby data structure from a JSON _source_ and return it. A source can # either be a string-like object, an IO-like object, or an object responding # to the read method. If _proc_ was given, it will be called with any nested # Ruby object as an argument recursively in depth first order. To modify the # default options pass in the optional _options_ argument as well. # # BEWARE: This method is meant to serialise data from trusted user input, # like from your own database server or clients under your control, it could # be dangerous to allow untrusted users to pass JSON sources into it. The # default options for the parser can be changed via the load_default_options # method. # # This method is part of the implementation of the load/dump interface of # Marshal and YAML. def load(source, proc = nil, options = {}) opts = load_default_options.merge options if source.respond_to? :to_str source = source.to_str elsif source.respond_to? :to_io source = source.to_io.read elsif source.respond_to?(:read) source = source.read end if opts[:quirks_mode] && (source.nil? || source.empty?) source = 'null' end result = parse(source, opts) recurse_proc(result, &proc) if proc result end # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_ def recurse_proc(result, &proc) case result when Array result.each { |x| recurse_proc x, &proc } proc.call result when Hash result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc } proc.call result else proc.call result end end alias restore load module_function :restore class << self # The global default options for the JSON.dump method: # :max_nesting: false # :allow_nan: true # :quirks_mode: true attr_accessor :dump_default_options end self.dump_default_options = { :max_nesting => false, :allow_nan => true, :quirks_mode => true, } # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns # the result. # # If anIO (an IO-like object or an object that responds to the write method) # was given, the resulting JSON is written to it. # # If the number of nested arrays or objects exceeds _limit_, an ArgumentError # exception is raised. This argument is similar (but not exactly the # same!) to the _limit_ argument in Marshal.dump. # # The default options for the generator can be changed via the # dump_default_options method. # # This method is part of the implementation of the load/dump interface of # Marshal and YAML. def dump(obj, anIO = nil, limit = nil) if anIO and limit.nil? anIO = anIO.to_io if anIO.respond_to?(:to_io) unless anIO.respond_to?(:write) limit = anIO anIO = nil end end opts = JSON.dump_default_options limit and opts.update(:max_nesting => limit) result = generate(obj, opts) if anIO anIO.write result anIO else result end rescue JSON::NestingError raise ArgumentError, "exceed depth limit" end # Swap consecutive bytes of _string_ in place. def self.swap!(string) # :nodoc: 0.upto(string.size / 2) do |i| break unless string[2 * i + 1] string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i] end string end # Shortuct for iconv. if ::String.method_defined?(:encode) && # XXX Rubinius doesn't support ruby 1.9 encoding yet defined?(RUBY_ENGINE) && RUBY_ENGINE != 'rbx' then # Encodes string using Ruby's _String.encode_ def self.iconv(to, from, string) string.encode(to, from) end else require 'iconv' # Encodes string using _iconv_ library def self.iconv(to, from, string) Iconv.conv(to, from, string) end end if ::Object.method(:const_defined?).arity == 1 def self.const_defined_in?(modul, constant) modul.const_defined?(constant) end else def self.const_defined_in?(modul, constant) modul.const_defined?(constant, false) end end end module ::Kernel private # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in # one line. def j(*objs) objs.each do |obj| puts JSON::generate(obj, :allow_nan => true, :max_nesting => false) end nil end # Ouputs _objs_ to STDOUT as JSON strings in a pretty format, with # indentation and over many lines. def jj(*objs) objs.each do |obj| puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false) end nil end # If _object_ is string-like, parse the string and return the parsed result as # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data # structure object and return it. # # The _opts_ argument is passed through to generate/parse respectively. See # generate and parse for their documentation. def JSON(object, *args) if object.respond_to? :to_str JSON.parse(object.to_str, args.first) else JSON.generate(object, args.first) end end end # Extends any Class to include _json_creatable?_ method. class ::Class # Returns true if this class can be used to create an instance # from a serialised JSON string. The class has to implement a class # method _json_create_ that expects a hash as first parameter. The hash # should include the required data. def json_creatable? respond_to?(:json_create) end end json/generic_object.rb000064400000002120147635506700011014 0ustar00require 'ostruct' module JSON class GenericObject < OpenStruct class << self alias [] new def json_creatable? @json_creatable end attr_writer :json_creatable def json_create(data) data = data.dup data.delete JSON.create_id self[data] end def from_hash(object) case when object.respond_to?(:to_hash) result = new object.to_hash.each do |key, value| result[key] = from_hash(value) end result when object.respond_to?(:to_ary) object.to_ary.map { |a| from_hash(a) } else object end end end self.json_creatable = false def to_hash table end def [](name) table[name.to_sym] end def []=(name, value) __send__ "#{name}=", value end def |(other) self.class[other.to_hash.merge(to_hash)] end def as_json(*) { JSON.create_id => self.class.name }.merge to_hash end def to_json(*a) as_json.to_json(*a) end end end json/add/range.rb000064400000001432147635506700007703 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end # Range serialization/deserialization class Range # Deserializes JSON string by constructing new Range object with arguments # a serialized by to_json. def self.json_create(object) new(*object['a']) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'a' => [ first, last, exclude_end? ] } end # Stores class name (Range) with JSON array of arguments a which # include first (integer), last (integer), and # exclude_end? (boolean) as JSON string. def to_json(*args) as_json.to_json(*args) end end json/add/complex.rb000064400000000616147635506700010261 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end defined?(::Complex) or require 'complex' class Complex def self.json_create(object) Complex(object['r'], object['i']) end def as_json(*) { JSON.create_id => self.class.name, 'r' => real, 'i' => imag, } end def to_json(*) as_json.to_json end end json/add/struct.rb000064400000001433147635506700010134 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end # Struct serialization/deserialization class Struct # Deserializes JSON string by constructing new Struct object with values # v serialized by to_json. def self.json_create(object) new(*object['v']) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" { JSON.create_id => klass, 'v' => values, } end # Stores class name (Struct) with Struct values v as a JSON string. # Only named structs are supported. def to_json(*args) as_json.to_json(*args) end end json/add/bigdecimal.rb000064400000001070147635506700010665 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end defined?(::BigDecimal) or require 'bigdecimal' class BigDecimal # Import a JSON Marshalled object. # # method used for JSON marshalling support. def self.json_create(object) BigDecimal._load object['b'] end # Marshal the object to JSON. # # method used for JSON marshalling support. def as_json(*) { JSON.create_id => self.class.name, 'b' => _dump, } end # return the JSON value def to_json(*) as_json.to_json end end json/add/time.rb000064400000002011147635506700007537 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end # Time serialization/deserialization class Time # Deserializes JSON string by converting time since epoch to Time def self.json_create(object) if usec = object.delete('u') # used to be tv_usec -> tv_nsec object['n'] = usec * 1000 end if instance_methods.include?(:tv_nsec) at(object['s'], Rational(object['n'], 1000)) else at(object['s'], object['n'] / 1000) end end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) nanoseconds = [ tv_usec * 1000 ] respond_to?(:tv_nsec) and nanoseconds << tv_nsec nanoseconds = nanoseconds.max { JSON.create_id => self.class.name, 's' => tv_sec, 'n' => nanoseconds, } end # Stores class name (Time) with number of seconds since epoch and number of # microseconds for Time as JSON string def to_json(*args) as_json.to_json(*args) end end json/add/core.rb000064400000000476147635506700007546 0ustar00# This file requires the implementations of ruby core's custom objects for # serialisation/deserialisation. require 'json/add/date' require 'json/add/date_time' require 'json/add/exception' require 'json/add/range' require 'json/add/regexp' require 'json/add/struct' require 'json/add/symbol' require 'json/add/time' json/add/symbol.rb000064400000001157147635506700010120 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end # Symbol serialization/deserialization class Symbol # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 's' => to_s, } end # Stores class name (Symbol) with String representation of Symbol as a JSON string. def to_json(*a) as_json.to_json(*a) end # Deserializes JSON string by converting the string value stored in the object to a Symbol def self.json_create(o) o['s'].to_sym end end json/add/regexp.rb000064400000001401147635506700010075 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end # Regexp serialization/deserialization class Regexp # Deserializes JSON string by constructing new Regexp object with source # s (Regexp or String) and options o serialized by # to_json def self.json_create(object) new(object['s'], object['o']) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'o' => options, 's' => source, } end # Stores class name (Regexp) with options o and source s # (Regexp or String) as JSON string def to_json(*) as_json.to_json end end json/add/date_time.rb000064400000002473147635506700010550 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end require 'date' # DateTime serialization/deserialization class DateTime # Deserializes JSON string by converting year y, month m, # day d, hour H, minute M, second S, # offset of and Day of Calendar Reform sg to DateTime. def self.json_create(object) args = object.values_at('y', 'm', 'd', 'H', 'M', 'S') of_a, of_b = object['of'].split('/') if of_b and of_b != '0' args << Rational(of_a.to_i, of_b.to_i) else args << of_a end args << object['sg'] civil(*args) end alias start sg unless method_defined?(:start) # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'y' => year, 'm' => month, 'd' => day, 'H' => hour, 'M' => min, 'S' => sec, 'of' => offset.to_s, 'sg' => start, } end # Stores class name (DateTime) with Julian year y, month m, # day d, hour H, minute M, second S, # offset of and Day of Calendar Reform sg as JSON string def to_json(*args) as_json.to_json(*args) end end json/add/exception.rb000064400000001453147635506700010610 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end # Exception serialization/deserialization class Exception # Deserializes JSON string by constructing new Exception object with message # m and backtrace b serialized with to_json def self.json_create(object) result = new(object['m']) result.set_backtrace object['b'] result end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'm' => message, 'b' => backtrace, } end # Stores class name (Exception) with message m and backtrace array # b as JSON string def to_json(*args) as_json.to_json(*args) end end json/add/date.rb000064400000001570147635506700007527 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end require 'date' # Date serialization/deserialization class Date # Deserializes JSON string by converting Julian year y, month # m, day d and Day of Calendar Reform sg to Date. def self.json_create(object) civil(*object.values_at('y', 'm', 'd', 'sg')) end alias start sg unless method_defined?(:start) # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) { JSON.create_id => self.class.name, 'y' => year, 'm' => month, 'd' => day, 'sg' => start, } end # Stores class name (Date) with Julian year y, month m, day # d and Day of Calendar Reform sg as JSON string def to_json(*args) as_json.to_json(*args) end end json/add/ostruct.rb000064400000001452147635506700010314 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end require 'ostruct' # OpenStruct serialization/deserialization class OpenStruct # Deserializes JSON string by constructing new Struct object with values # v serialized by to_json. def self.json_create(object) new(object['t'] || object[:t]) end # Returns a hash, that will be turned into a JSON object and represent this # object. def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" { JSON.create_id => klass, 't' => table, } end # Stores class name (OpenStruct) with this struct's values v as a # JSON string. def to_json(*args) as_json.to_json(*args) end end json/add/rational.rb000064400000000636147635506700010425 0ustar00unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end defined?(::Rational) or require 'rational' class Rational def self.json_create(object) Rational(object['n'], object['d']) end def as_json(*) { JSON.create_id => self.class.name, 'n' => numerator, 'd' => denominator, } end def to_json(*) as_json.to_json end end json/ext.rb000064400000000774147635506700006667 0ustar00if ENV['SIMPLECOV_COVERAGE'].to_i == 1 require 'simplecov' SimpleCov.start do add_filter "/tests/" end end require 'json/common' module JSON # This module holds all the modules/classes that implement JSON's # functionality as C extensions. module Ext require 'json/ext/parser' require 'json/ext/generator' $DEBUG and warn "Using Ext extension for JSON." JSON.parser = Parser JSON.generator = Generator end JSON_LOADED = true unless defined?(::JSON::JSON_LOADED) end json/version.rb000064400000000417147635506700007546 0ustar00module JSON # JSON version VERSION = '1.7.7' VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: VERSION_BUILD = VERSION_ARRAY[2] # :nodoc: end json.rb000064400000003363147635506700006064 0ustar00require 'json/common' ## # = JavaScript Object Notation (JSON) # # JSON is a lightweight data-interchange format. It is easy for us # humans to read and write. Plus, equally simple for machines to generate or parse. # JSON is completely language agnostic, making it the ideal interchange format. # # Built on two universally available structures: # 1. A collection of name/value pairs. Often referred to as an _object_, hash table, record, struct, keyed list, or associative array. # 2. An ordered list of values. More commonly called an _array_, vector, sequence or list. # # To read more about JSON visit: http://json.org # # == Parsing JSON # # To parse a JSON string received by another application or generated within # your existing application: # # require 'json' # # my_hash = JSON.parse('{"hello": "goodbye"}') # puts my_hash["hello"] => "goodbye" # # Notice the extra quotes '' around the hash notation. Ruby expects # the argument to be a string and can't convert objects like a hash or array. # # Ruby converts your string into a hash # # == Generating JSON # # Creating a JSON string for communication or serialization is # just as simple. # # require 'json' # # my_hash = {:hello => "goodbye"} # puts JSON.generate(my_hash) => "{\"hello\":\"goodbye\"}" # # Or an alternative way: # # require 'json' # puts {:hello => "goodbye"}.to_json => "{\"hello\":\"goodbye\"}" # # JSON.generate only allows objects or arrays to be converted # to JSON syntax. to_json, however, accepts many Ruby classes # even though it acts only as a method for serialization: # # require 'json' # # 1.to_json => "1" # module JSON require 'json/version' begin require 'json/ext' rescue LoadError require 'json/pure' end end