1 | require "rdoc/parsers/parse_simple"
|
---|
2 |
|
---|
3 | module RDoc
|
---|
4 |
|
---|
5 | # A parser is simple a class that implements
|
---|
6 | #
|
---|
7 | # #initialize(file_name, body, options)
|
---|
8 | #
|
---|
9 | # and
|
---|
10 | #
|
---|
11 | # #scan
|
---|
12 | #
|
---|
13 | # The initialize method takes a file name to be used, the body of the
|
---|
14 | # file, and an RDoc::Options object. The scan method is then called
|
---|
15 | # to return an appropriately parsed TopLevel code object.
|
---|
16 | #
|
---|
17 | # The ParseFactory is used to redirect to the correct parser given a filename
|
---|
18 | # extension. This magic works because individual parsers have to register
|
---|
19 | # themselves with us as they are loaded in. The do this using the following
|
---|
20 | # incantation
|
---|
21 | #
|
---|
22 | #
|
---|
23 | # require "rdoc/parsers/parsefactory"
|
---|
24 | #
|
---|
25 | # module RDoc
|
---|
26 | #
|
---|
27 | # class XyzParser
|
---|
28 | # extend ParseFactory <<<<
|
---|
29 | # parse_files_matching /\.xyz$/ <<<<
|
---|
30 | #
|
---|
31 | # def initialize(file_name, body, options)
|
---|
32 | # ...
|
---|
33 | # end
|
---|
34 | #
|
---|
35 | # def scan
|
---|
36 | # ...
|
---|
37 | # end
|
---|
38 | # end
|
---|
39 | # end
|
---|
40 | #
|
---|
41 | # Just to make life interesting, if we suspect a plain text file, we
|
---|
42 | # also look for a shebang line just in case it's a potential
|
---|
43 | # shell script
|
---|
44 |
|
---|
45 |
|
---|
46 |
|
---|
47 | module ParserFactory
|
---|
48 |
|
---|
49 | @@parsers = []
|
---|
50 |
|
---|
51 | Parsers = Struct.new(:regexp, :parser)
|
---|
52 |
|
---|
53 | # Record the fact that a particular class parses files that
|
---|
54 | # match a given extension
|
---|
55 |
|
---|
56 | def parse_files_matching(regexp)
|
---|
57 | @@parsers.unshift Parsers.new(regexp, self)
|
---|
58 | end
|
---|
59 |
|
---|
60 | # Return a parser that can handle a particular extension
|
---|
61 |
|
---|
62 | def ParserFactory.can_parse(file_name)
|
---|
63 | @@parsers.find {|p| p.regexp.match(file_name) }
|
---|
64 | end
|
---|
65 |
|
---|
66 | # Alias an extension to another extension. After this call,
|
---|
67 | # files ending "new_ext" will be parsed using the same parser
|
---|
68 | # as "old_ext"
|
---|
69 |
|
---|
70 | def ParserFactory.alias_extension(old_ext, new_ext)
|
---|
71 | parser = ParserFactory.can_parse("xxx.#{old_ext}")
|
---|
72 | return false unless parser
|
---|
73 | @@parsers.unshift Parsers.new(Regexp.new("\\.#{new_ext}$"), parser.parser)
|
---|
74 | true
|
---|
75 | end
|
---|
76 |
|
---|
77 | # Find the correct parser for a particular file name. Return a
|
---|
78 | # SimpleParser for ones that we don't know
|
---|
79 |
|
---|
80 | def ParserFactory.parser_for(top_level, file_name, body, options, stats)
|
---|
81 | # If no extension, look for shebang
|
---|
82 | if file_name !~ /\.\w+$/ && body =~ %r{\A#!(.+)}
|
---|
83 | shebang = $1
|
---|
84 | case shebang
|
---|
85 | when %r{env\s+ruby}, %r{/ruby}
|
---|
86 | file_name = "dummy.rb"
|
---|
87 | end
|
---|
88 | end
|
---|
89 | parser_description = can_parse(file_name)
|
---|
90 | if parser_description
|
---|
91 | parser = parser_description.parser
|
---|
92 | else
|
---|
93 | parser = SimpleParser
|
---|
94 | end
|
---|
95 |
|
---|
96 | parser.new(top_level, file_name, body, options, stats)
|
---|
97 | end
|
---|
98 | end
|
---|
99 | end
|
---|