~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to lib/rdoc/parser/perl.rb

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
require 'rdoc/parser'
2
 
 
3
 
##
4
 
#
5
 
# This is an attamept to write a basic parser for Perl's
6
 
# POD (Plain old Documentation) format.  Ruby code must
7
 
# co-exist with Perl, and some tasks are easier in Perl
8
 
# than Ruby because of existing libraries.
9
 
#
10
 
# One difficult is that Perl POD has no means of identifying
11
 
# the classes (packages) and methods (subs) with which it
12
 
# is associated, it is more like literate programming in so
13
 
# far as it just happens to be in the same place as the code,
14
 
# but need not be.
15
 
#
16
 
# We would like to support all the markup the POD provides
17
 
# so that it will convert happily to HTML.  At the moment
18
 
# I don't think I can do that: time constraints.
19
 
#
20
 
 
21
 
class RDoc::Parser::PerlPOD < RDoc::Parser
22
 
 
23
 
  parse_files_matching(/.p[lm]$/)
24
 
 
25
 
  ##
26
 
  # Prepare to parse a perl file
27
 
 
28
 
  def initialize(top_level, file_name, content, options, stats)
29
 
    super
30
 
 
31
 
    preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
32
 
 
33
 
    preprocess.handle @content do |directive, param|
34
 
      warn "Unrecognized directive '#{directive}' in #{@file_name}"
35
 
    end
36
 
  end
37
 
 
38
 
  ##
39
 
  # Extract the Pod(-like) comments from the code.
40
 
  # At its most basic there will ne no need to distinguish
41
 
  # between the different types of header, etc.
42
 
  #
43
 
  # This uses a simple finite state machine, in a very
44
 
  # procedural pattern. I could "replace case with polymorphism"
45
 
  # but I think it would obscure the intent, scatter the
46
 
  # code all over tha place.  This machine is necessary
47
 
  # because POD requires that directives be preceded by
48
 
  # blank lines, so reading line by line is necessary,
49
 
  # and preserving state about what is seen is necesary.
50
 
 
51
 
  def scan
52
 
 
53
 
    @top_level.comment ||= ""
54
 
    state=:code_blank
55
 
    line_number = 0
56
 
    line = nil
57
 
 
58
 
    # This started out as a really long nested case statement,
59
 
    # which also led to repetitive code.  I'd like to avoid that
60
 
    # so I'm using a "table" instead.
61
 
 
62
 
    # Firstly we need some procs to do the transition and processing
63
 
    # work.  Because these are procs they are closures, and they can
64
 
    # use variables in the local scope.
65
 
    #
66
 
    # First, the "nothing to see here" stuff.
67
 
    code_noop = lambda do
68
 
      if line =~ /^\s+$/
69
 
        state = :code_blank
70
 
      end
71
 
    end
72
 
 
73
 
    pod_noop = lambda do
74
 
      if line =~ /^\s+$/
75
 
        state = :pod_blank
76
 
      end
77
 
      @top_level.comment += filter(line)
78
 
    end
79
 
 
80
 
    begin_noop = lambda do
81
 
      if line =~ /^\s+$/
82
 
        state = :begin_blank
83
 
      end
84
 
      @top_level.comment += filter(line)
85
 
    end
86
 
 
87
 
    # Now for the blocks that process code and comments...
88
 
 
89
 
    transit_to_pod = lambda do
90
 
      case line
91
 
      when /^=(?:pod|head\d+)/
92
 
        state = :pod_no_blank
93
 
        @top_level.comment += filter(line)
94
 
      when /^=over/
95
 
        state = :over_no_blank
96
 
        @top_level.comment += filter(line)
97
 
      when /^=(?:begin|for)/
98
 
        state = :begin_no_blank
99
 
      end
100
 
    end
101
 
 
102
 
    process_pod = lambda do
103
 
      case line
104
 
      when  /^\s*$/
105
 
        state = :pod_blank
106
 
        @top_level.comment += filter(line)
107
 
      when /^=cut/
108
 
        state = :code_no_blank
109
 
      when /^=end/
110
 
        $stderr.puts "'=end' unexpected at #{line_number} in #{@file_name}"
111
 
      else
112
 
        @top_level.comment += filter(line)
113
 
      end
114
 
    end
115
 
 
116
 
 
117
 
    process_begin = lambda do
118
 
      case line
119
 
      when  /^\s*$/
120
 
        state = :begin_blank
121
 
        @top_level.comment += filter(line)
122
 
      when /^=end/
123
 
        state = :code_no_blank
124
 
      when /^=cut/
125
 
        $stderr.puts "'=cut' unexpected at #{line_number} in #{@file_name}"
126
 
      else
127
 
        @top_level.comment += filter(line)
128
 
      end
129
 
 
130
 
    end
131
 
 
132
 
 
133
 
    transitions = { :code_no_blank => code_noop,
134
 
                    :code_blank => transit_to_pod,
135
 
                    :pod_no_blank => pod_noop,
136
 
                    :pod_blank => process_pod,
137
 
                    :begin_no_blank => begin_noop,
138
 
                    :begin_blank => process_begin}
139
 
    @content.each_line do |l|
140
 
      line = l
141
 
      line_number += 1
142
 
      transitions[state].call
143
 
    end # each line
144
 
 
145
 
    @top_level
146
 
  end
147
 
 
148
 
  # Filter the perl markup that does the same as the rdoc
149
 
  # filtering.  Only basic for now. Will probably need a
150
 
  # proper parser to cope with C<<...>> etc
151
 
  def filter(comment)
152
 
    return '' if comment =~ /^=pod\s*$/
153
 
    comment.gsub!(/^=pod/, '==')
154
 
    comment.gsub!(/^=head(\d+)/) do
155
 
      "=" * $1.to_i
156
 
    end
157
 
    comment.gsub!(/=item/, '');
158
 
    comment.gsub!(/C<(.*?)>/, '<tt>\1</tt>');
159
 
    comment.gsub!(/I<(.*?)>/, '<i>\1</i>');
160
 
    comment.gsub!(/B<(.*?)>/, '<b>\1</b>');
161
 
    comment
162
 
  end
163
 
 
164
 
end
165