sqlpostgres 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +22 -0
  3. data/LICENSE.md +23 -0
  4. data/README.rdoc +59 -0
  5. data/Rakefile +32 -0
  6. data/VERSION +1 -0
  7. data/doc/BUGS +2 -0
  8. data/doc/examples/README +6 -0
  9. data/doc/examples/connection.rb +16 -0
  10. data/doc/examples/connection_auto.rb +22 -0
  11. data/doc/examples/connection_ctor.rb +18 -0
  12. data/doc/examples/connection_default.rb +15 -0
  13. data/doc/examples/connection_exec.rb +18 -0
  14. data/doc/examples/connection_manual.rb +12 -0
  15. data/doc/examples/connection_wrapped_new.rb +13 -0
  16. data/doc/examples/connection_wrapped_open.rb +13 -0
  17. data/doc/examples/cursor.rb +38 -0
  18. data/doc/examples/include_module.rb +9 -0
  19. data/doc/examples/include_module2.rb +12 -0
  20. data/doc/examples/insert.rb +30 -0
  21. data/doc/examples/insert2.rb +36 -0
  22. data/doc/examples/insert_bytea.rb +16 -0
  23. data/doc/examples/insert_bytea_array.rb +17 -0
  24. data/doc/examples/insert_default_values.rb +16 -0
  25. data/doc/examples/insert_insert.rb +16 -0
  26. data/doc/examples/insert_insert_default.rb +16 -0
  27. data/doc/examples/insert_insert_select.rb +20 -0
  28. data/doc/examples/insert_select.rb +20 -0
  29. data/doc/examples/interval.rb +17 -0
  30. data/doc/examples/savepoint.rb +38 -0
  31. data/doc/examples/select.rb +33 -0
  32. data/doc/examples/select2.rb +36 -0
  33. data/doc/examples/select_cross_join.rb +18 -0
  34. data/doc/examples/select_distinct.rb +18 -0
  35. data/doc/examples/select_distinct_on +19 -0
  36. data/doc/examples/select_for_update.rb +18 -0
  37. data/doc/examples/select_from.rb +17 -0
  38. data/doc/examples/select_from_subselect.rb +20 -0
  39. data/doc/examples/select_group_by.rb +19 -0
  40. data/doc/examples/select_having.rb +20 -0
  41. data/doc/examples/select_join_on.rb +18 -0
  42. data/doc/examples/select_join_using.rb +18 -0
  43. data/doc/examples/select_limit.rb +19 -0
  44. data/doc/examples/select_natural_join.rb +18 -0
  45. data/doc/examples/select_offset.rb +19 -0
  46. data/doc/examples/select_order_by.rb +20 -0
  47. data/doc/examples/select_select.rb +30 -0
  48. data/doc/examples/select_select_alias.rb +30 -0
  49. data/doc/examples/select_select_expression.rb +31 -0
  50. data/doc/examples/select_select_literal.rb +24 -0
  51. data/doc/examples/select_union.rb +21 -0
  52. data/doc/examples/select_where_array.rb +18 -0
  53. data/doc/examples/select_where_in.rb +18 -0
  54. data/doc/examples/select_where_string.rb +18 -0
  55. data/doc/examples/simple.rb +34 -0
  56. data/doc/examples/transaction.rb +30 -0
  57. data/doc/examples/transaction_abort.rb +30 -0
  58. data/doc/examples/transaction_commit.rb +34 -0
  59. data/doc/examples/translate_substitute_values.rb +17 -0
  60. data/doc/examples/update.rb +32 -0
  61. data/doc/examples/update2.rb +44 -0
  62. data/doc/examples/update_only.rb +17 -0
  63. data/doc/examples/update_set.rb +17 -0
  64. data/doc/examples/update_set_array.rb +16 -0
  65. data/doc/examples/update_set_bytea.rb +16 -0
  66. data/doc/examples/update_set_expression.rb +16 -0
  67. data/doc/examples/update_set_subselect.rb +20 -0
  68. data/doc/examples/update_where.rb +17 -0
  69. data/doc/examples/use_prefix.rb +8 -0
  70. data/doc/examples/use_prefix2.rb +11 -0
  71. data/doc/index.html +31 -0
  72. data/doc/insertexamples.rb +9 -0
  73. data/doc/makemanual +4 -0
  74. data/doc/makerdoc +5 -0
  75. data/doc/manual.dbk +622 -0
  76. data/lib/sqlpostgres/Connection.rb +198 -0
  77. data/lib/sqlpostgres/Cursor.rb +157 -0
  78. data/lib/sqlpostgres/Delete.rb +67 -0
  79. data/lib/sqlpostgres/Exceptions.rb +15 -0
  80. data/lib/sqlpostgres/Insert.rb +279 -0
  81. data/lib/sqlpostgres/NullConnection.rb +22 -0
  82. data/lib/sqlpostgres/PgBit.rb +73 -0
  83. data/lib/sqlpostgres/PgBox.rb +37 -0
  84. data/lib/sqlpostgres/PgCidr.rb +21 -0
  85. data/lib/sqlpostgres/PgCircle.rb +75 -0
  86. data/lib/sqlpostgres/PgInet.rb +21 -0
  87. data/lib/sqlpostgres/PgInterval.rb +208 -0
  88. data/lib/sqlpostgres/PgLineSegment.rb +37 -0
  89. data/lib/sqlpostgres/PgMacAddr.rb +21 -0
  90. data/lib/sqlpostgres/PgPath.rb +64 -0
  91. data/lib/sqlpostgres/PgPoint.rb +65 -0
  92. data/lib/sqlpostgres/PgPolygon.rb +56 -0
  93. data/lib/sqlpostgres/PgTime.rb +77 -0
  94. data/lib/sqlpostgres/PgTimeWithTimeZone.rb +98 -0
  95. data/lib/sqlpostgres/PgTimestamp.rb +93 -0
  96. data/lib/sqlpostgres/PgTwoPoints.rb +54 -0
  97. data/lib/sqlpostgres/PgType.rb +34 -0
  98. data/lib/sqlpostgres/PgWrapper.rb +41 -0
  99. data/lib/sqlpostgres/Savepoint.rb +98 -0
  100. data/lib/sqlpostgres/Select.rb +855 -0
  101. data/lib/sqlpostgres/Transaction.rb +120 -0
  102. data/lib/sqlpostgres/Translate.rb +436 -0
  103. data/lib/sqlpostgres/Update.rb +188 -0
  104. data/lib/sqlpostgres.rb +67 -0
  105. data/test/Assert.rb +72 -0
  106. data/test/Connection.test.rb +246 -0
  107. data/test/Cursor.test.rb +190 -0
  108. data/test/Delete.test.rb +68 -0
  109. data/test/Insert.test.rb +123 -0
  110. data/test/MockPGconn.rb +62 -0
  111. data/test/NullConnection.test.rb +32 -0
  112. data/test/PgBit.test.rb +98 -0
  113. data/test/PgBox.test.rb +108 -0
  114. data/test/PgCidr.test.rb +61 -0
  115. data/test/PgCircle.test.rb +107 -0
  116. data/test/PgInet.test.rb +61 -0
  117. data/test/PgInterval.test.rb +180 -0
  118. data/test/PgLineSegment.test.rb +108 -0
  119. data/test/PgMacAddr.test.rb +61 -0
  120. data/test/PgPath.test.rb +106 -0
  121. data/test/PgPoint.test.rb +100 -0
  122. data/test/PgPolygon.test.rb +95 -0
  123. data/test/PgTime.test.rb +120 -0
  124. data/test/PgTimeWithTimeZone.test.rb +117 -0
  125. data/test/PgTimestamp.test.rb +134 -0
  126. data/test/RandomThings.rb +25 -0
  127. data/test/Savepoint.test.rb +286 -0
  128. data/test/Select.test.rb +930 -0
  129. data/test/Test.rb +62 -0
  130. data/test/TestConfig.rb +21 -0
  131. data/test/TestSetup.rb +13 -0
  132. data/test/TestUtil.rb +92 -0
  133. data/test/Transaction.test.rb +275 -0
  134. data/test/Translate.test.rb +354 -0
  135. data/test/Update.test.rb +227 -0
  136. data/test/roundtrip.test.rb +565 -0
  137. data/test/test +34 -0
  138. data/tools/exampleinserter/ExampleInserter.rb +177 -0
  139. data/tools/rdoc/ChangeLog +796 -0
  140. data/tools/rdoc/EXAMPLE.rb +48 -0
  141. data/tools/rdoc/MANIFEST +58 -0
  142. data/tools/rdoc/Makefile +27 -0
  143. data/tools/rdoc/NEW_FEATURES +226 -0
  144. data/tools/rdoc/README +390 -0
  145. data/tools/rdoc/ToDo +6 -0
  146. data/tools/rdoc/contrib/Index +6 -0
  147. data/tools/rdoc/contrib/xslfo/ChangeLog +181 -0
  148. data/tools/rdoc/contrib/xslfo/README +106 -0
  149. data/tools/rdoc/contrib/xslfo/TODO +10 -0
  150. data/tools/rdoc/contrib/xslfo/convert.xsl +151 -0
  151. data/tools/rdoc/contrib/xslfo/demo/README +21 -0
  152. data/tools/rdoc/contrib/xslfo/demo/rdocfo +99 -0
  153. data/tools/rdoc/contrib/xslfo/fcm.xsl +54 -0
  154. data/tools/rdoc/contrib/xslfo/files.xsl +62 -0
  155. data/tools/rdoc/contrib/xslfo/labeled-lists.xsl +66 -0
  156. data/tools/rdoc/contrib/xslfo/lists.xsl +44 -0
  157. data/tools/rdoc/contrib/xslfo/modules.xsl +152 -0
  158. data/tools/rdoc/contrib/xslfo/rdoc.xsl +75 -0
  159. data/tools/rdoc/contrib/xslfo/source.xsl +66 -0
  160. data/tools/rdoc/contrib/xslfo/styles.xsl +69 -0
  161. data/tools/rdoc/contrib/xslfo/tables.xsl +67 -0
  162. data/tools/rdoc/contrib/xslfo/utils.xsl +21 -0
  163. data/tools/rdoc/debian/changelog +33 -0
  164. data/tools/rdoc/debian/compat +1 -0
  165. data/tools/rdoc/debian/control +20 -0
  166. data/tools/rdoc/debian/copyright +10 -0
  167. data/tools/rdoc/debian/dirs +2 -0
  168. data/tools/rdoc/debian/docs +2 -0
  169. data/tools/rdoc/debian/rdoc.1 +252 -0
  170. data/tools/rdoc/debian/rdoc.manpages +1 -0
  171. data/tools/rdoc/debian/rdoc.pod +149 -0
  172. data/tools/rdoc/debian/rules +9 -0
  173. data/tools/rdoc/dot/dot.rb +255 -0
  174. data/tools/rdoc/etc/rdoc.dtd +203 -0
  175. data/tools/rdoc/install.rb +137 -0
  176. data/tools/rdoc/markup/install.rb +43 -0
  177. data/tools/rdoc/markup/sample/sample.rb +42 -0
  178. data/tools/rdoc/markup/simple_markup/fragments.rb +323 -0
  179. data/tools/rdoc/markup/simple_markup/inline.rb +348 -0
  180. data/tools/rdoc/markup/simple_markup/lines.rb +147 -0
  181. data/tools/rdoc/markup/simple_markup/preprocess.rb +68 -0
  182. data/tools/rdoc/markup/simple_markup/to_html.rb +281 -0
  183. data/tools/rdoc/markup/simple_markup.rb +474 -0
  184. data/tools/rdoc/markup/test/AllTests.rb +2 -0
  185. data/tools/rdoc/markup/test/TestInline.rb +151 -0
  186. data/tools/rdoc/markup/test/TestParse.rb +411 -0
  187. data/tools/rdoc/rdoc/code_objects.rb +536 -0
  188. data/tools/rdoc/rdoc/diagram.rb +331 -0
  189. data/tools/rdoc/rdoc/generators/chm_generator.rb +112 -0
  190. data/tools/rdoc/rdoc/generators/html_generator.rb +1268 -0
  191. data/tools/rdoc/rdoc/generators/template/chm/chm.rb +86 -0
  192. data/tools/rdoc/rdoc/generators/template/html/html.rb +705 -0
  193. data/tools/rdoc/rdoc/generators/template/html/kilmer.rb +377 -0
  194. data/tools/rdoc/rdoc/generators/template/xml/rdf.rb +110 -0
  195. data/tools/rdoc/rdoc/generators/template/xml/xml.rb +110 -0
  196. data/tools/rdoc/rdoc/generators/xml_generator.rb +130 -0
  197. data/tools/rdoc/rdoc/options.rb +451 -0
  198. data/tools/rdoc/rdoc/parsers/parse_c.rb +287 -0
  199. data/tools/rdoc/rdoc/parsers/parse_f95.rb +118 -0
  200. data/tools/rdoc/rdoc/parsers/parse_rb.rb +2311 -0
  201. data/tools/rdoc/rdoc/parsers/parse_simple.rb +37 -0
  202. data/tools/rdoc/rdoc/parsers/parserfactory.rb +75 -0
  203. data/tools/rdoc/rdoc/rdoc.rb +219 -0
  204. data/tools/rdoc/rdoc/template.rb +234 -0
  205. data/tools/rdoc/rdoc/tokenstream.rb +25 -0
  206. data/tools/rdoc/rdoc.rb +9 -0
  207. metadata +291 -0
@@ -0,0 +1,287 @@
1
+ # We attempt to parse C extension files. Basically we look for
2
+ # the standard patterns that you find in extensions: <tt>rb_define_class,
3
+ # rb_define_method</tt> and so on. We also try to find the corresponding
4
+ # C source for the methods and extract comments, but if we fail
5
+ # we don't worry too much.
6
+ #
7
+ # The comments associated with a Ruby method are extracted from the C
8
+ # comment block associated with the routine that _implements_ that
9
+ # method, that is to say the method whose name is given in the
10
+ # <tt>rb_define_method</tt> call. For example, you might write:
11
+ #
12
+ # /*
13
+ # * Returns a new array that is a one-dimensional flattening of this
14
+ # * array (recursively). That is, for every element that is an array,
15
+ # * extract its elements into the new array.
16
+ # *
17
+ # * s = [ 1, 2, 3 ] #=> [1, 2, 3]
18
+ # * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
19
+ # * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
20
+ # * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
21
+ # */
22
+ # static VALUE
23
+ # rb_ary_flatten(ary)
24
+ # VALUE ary;
25
+ # {
26
+ # ary = rb_obj_dup(ary);
27
+ # rb_ary_flatten_bang(ary);
28
+ # return ary;
29
+ # }
30
+ #
31
+ # ...
32
+ #
33
+ # void
34
+ # Init_Array()
35
+ # {
36
+ # ...
37
+ # rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
38
+ #
39
+ # Here RDoc will determine from the rb_define_method line that there's a
40
+ # method called "flatten" in class Array, and will look for the implementation
41
+ # in the method rb_ary_flatten. It will then use the comment from that
42
+ # method in the HTML output. This method must be in the same source file
43
+ # as the rb_define_method.
44
+ #
45
+ # C classes can be diagramed (see /tc/dl/ruby/ruby/error.c), and RDoc
46
+ # integrates C and Ruby source into one tree
47
+
48
+ # Classes and modules built in to the interpreter. We need
49
+ # these to define superclasses of user objects
50
+
51
+ require "rdoc/code_objects"
52
+ require "rdoc/parsers/parserfactory"
53
+
54
+
55
+ module RDoc
56
+
57
+ KNOWN_CLASSES = {
58
+ "rb_cObject" => "Object",
59
+ "rb_cArray" => "Array",
60
+ "rb_cBignum" => "Bignum",
61
+ "rb_cClass" => "Class",
62
+ "rb_cDir" => "Dir",
63
+ "rb_cData" => "Data",
64
+ "rb_cFalseClass" => "FalseClass",
65
+ "rb_cFile" => "File",
66
+ "rb_cFixnum" => "Fixnum",
67
+ "rb_cFloat" => "Float",
68
+ "rb_cHash" => "Hash",
69
+ "rb_cInteger" => "Integer",
70
+ "rb_cIO" => "IO",
71
+ "rb_cModule" => "Module",
72
+ "rb_cNilClass" => "NilClass",
73
+ "rb_cNumeric" => "Numeric",
74
+ "rb_cProc" => "Proc",
75
+ "rb_cRange" => "Range",
76
+ "rb_cRegexp" => "Regexp",
77
+ "rb_cString" => "String",
78
+ "rb_cSymbol" => "Symbol",
79
+ "rb_cThread" => "Thread",
80
+ "rb_cTime" => "Time",
81
+ "rb_cTrueClass" => "TrueClass",
82
+ "rb_cStruct" => "Struct",
83
+ "rb_eException" => "Exception",
84
+ "rb_eStandardError" => "StandardError",
85
+ "rb_eSystemExit" => "SystemExit",
86
+ "rb_eInterrupt" => "Interrupt",
87
+ "rb_eSignal" => "Signal",
88
+ "rb_eFatal" => "Fatal",
89
+ "rb_eArgError" => "ArgError",
90
+ "rb_eEOFError" => "EOFError",
91
+ "rb_eIndexError" => "IndexError",
92
+ "rb_eRangeError" => "RangeError",
93
+ "rb_eIOError" => "IOError",
94
+ "rb_eRuntimeError" => "RuntimeError",
95
+ "rb_eSecurityError" => "SecurityError",
96
+ "rb_eSystemCallError" => "SystemCallError",
97
+ "rb_eTypeError" => "TypeError",
98
+ "rb_eZeroDivError" => "ZeroDivError",
99
+ "rb_eNotImpError" => "NotImpError",
100
+ "rb_eNoMemError" => "NoMemError",
101
+ "rb_eFloatDomainError" => "FloatDomainError",
102
+ "rb_eScriptError" => "ScriptError",
103
+ "rb_eNameError" => "NameError",
104
+ "rb_eSyntaxError" => "SyntaxError",
105
+ "rb_eLoadError" => "LoadError",
106
+
107
+ "rb_mKernel" => "Kernel",
108
+ "rb_mComparable" => "Comparable",
109
+ "rb_mEnumerable" => "Enumerable",
110
+ "rb_mPrecision" => "Precision",
111
+ "rb_mErrno" => "Errno",
112
+ "rb_mFileTest" => "FileTest",
113
+ "rb_mGC" => "GC",
114
+ "rb_mMath" => "Math",
115
+ "rb_mProcess" => "Process"
116
+
117
+ }
118
+
119
+ # See rdoc/c_parse.rb
120
+
121
+ class C_Parser
122
+
123
+
124
+ extend ParserFactory
125
+ parse_files_matching(/\.(c|cc|cpp|CC)$/)
126
+
127
+
128
+ # prepare to parse a C file
129
+ def initialize(top_level, file_name, body, options)
130
+ @known_classes = KNOWN_CLASSES.dup
131
+ @body = body
132
+ @options = options
133
+ @top_level = top_level
134
+ @classes = Hash.new
135
+ end
136
+
137
+ # Extract the classes/modules and methods from a C file
138
+ # and return the corresponding top-level object
139
+ def scan
140
+ remove_commented_out_lines
141
+ do_classes
142
+ do_methods
143
+ @top_level
144
+ end
145
+
146
+ #######
147
+ private
148
+ #######
149
+
150
+ # remove lines that are commented out that might otherwise get
151
+ # picked up when scanning for classes and methods
152
+
153
+ def remove_commented_out_lines
154
+ @body.gsub!(%r{//.*rb_define_}, '//')
155
+ end
156
+
157
+ def handle_class_module(var_name, class_mod, class_name, parent, in_module)
158
+ @known_classes[var_name] = class_name
159
+ parent_name = @known_classes[parent] || parent
160
+
161
+ if in_module
162
+ enclosure = @classes[in_module]
163
+ unless enclosure
164
+ $stderr.puts("Enclosing class/module '#{in_module}' for " +
165
+ class_mod + " #{class_name} not known")
166
+ return
167
+ end
168
+ else
169
+ enclosure = @top_level
170
+ end
171
+
172
+ if class_mod == "class"
173
+ cm = enclosure.add_class(NormalClass, class_name, parent_name)
174
+ else
175
+ cm = enclosure.add_module(NormalModule, class_name)
176
+ end
177
+ cm.record_location(enclosure.toplevel)
178
+ @classes[var_name] = cm
179
+ end
180
+
181
+
182
+
183
+ def do_classes
184
+ @body.scan(/(\w+)\s* = \s*rb_define_module\(\s*"(\w+)"\s*\)/mx) do
185
+ |var_name, class_name|
186
+ handle_class_module(var_name, "module", class_name, nil, nil)
187
+ end
188
+
189
+ @body.scan(/(\w+)\s* = \s*rb_define_module_under
190
+ \(
191
+ \s*(\w+),
192
+ \s*"(\w+)"
193
+ \)/mx) do
194
+
195
+ |var_name, in_module, class_name|
196
+ handle_class_module(var_name, "module", class_name, nil, in_module)
197
+ end
198
+
199
+ @body.scan(/(\w+)\s* = \s*rb_define_class
200
+ \(
201
+ \s*"(\w+)",
202
+ \s*(\w+)\s*
203
+ \)/mx) do
204
+
205
+ |var_name, class_name, parent|
206
+ handle_class_module(var_name, "class", class_name, parent, nil)
207
+ end
208
+
209
+ @body.scan(/(\w+)\s* = \s*rb_define_class_under
210
+ \(
211
+ \s*(\w+),
212
+ \s*"(\w+)",
213
+ \s*(\w+)\s*
214
+ \)/mx) do
215
+
216
+ |var_name, in_module, class_name, parent|
217
+ handle_class_module(var_name, "class", class_name, parent, in_module)
218
+ end
219
+
220
+ end
221
+
222
+
223
+ def do_methods
224
+ @body.scan(/rb_define_(singleton_method|method|module_function)\(\s*(\w+),
225
+ \s*"(.*?)",
226
+ \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
227
+ \s*(-?\w+)\s*\)/xm) do
228
+ |type, var_name, meth_name, meth_body, param_count|
229
+
230
+ class_name = @known_classes[var_name] || var_name
231
+ class_obj = @classes[var_name]
232
+ if class_obj
233
+ meth_obj = AnyMethod.new("", meth_name)
234
+ meth_obj.singleton = type == "singleton_method"
235
+
236
+ p_count = (Integer(param_count) rescue -1)
237
+
238
+ if p_count < 0
239
+ meth_obj.params = "(...)"
240
+ elsif p_count == 0
241
+ meth_obj.params = "()"
242
+ else
243
+ meth_obj.params = "(" +
244
+ (1..p_count).map{|i| "p#{i}"}.join(", ") +
245
+ ")"
246
+ end
247
+
248
+ find_body(meth_body, meth_obj)
249
+ class_obj.add_method(meth_obj)
250
+ end
251
+ end
252
+ end
253
+
254
+ # Find the C code corresponding to a c method
255
+ def find_body(meth_name, meth_obj)
256
+ if @body =~ %r{((?>/\*.*?\*/\s+))(static\s+)?VALUE\s+#{meth_name}
257
+ \s*(\(.*?\)).*?^}xm
258
+ comment, params = $1, $3
259
+ body_text = $&
260
+
261
+ # see if we can find the whole body
262
+
263
+ re = Regexp.escape(body_text) + "[^(]*^{.*?^}"
264
+ if Regexp.new(re, Regexp::MULTILINE).match(@body)
265
+ body_text = $&
266
+ end
267
+
268
+ meth_obj.params = params
269
+ meth_obj.start_collecting_tokens
270
+ meth_obj.add_token(RubyToken::Token.new(1,1).set_text(body_text))
271
+ meth_obj.comment = mangle_comment(comment)
272
+
273
+ end
274
+ end
275
+
276
+ # Remove the /*'s and leading asterisks from C comments
277
+
278
+ def mangle_comment(comment)
279
+ comment.sub!(%r{/\*+}) { " " * $&.length }
280
+ comment.sub!(%r{\*+/}) { " " * $&.length }
281
+ comment.gsub!(/^[ \t]*\*/m) { " " * $&.length }
282
+ comment
283
+ end
284
+
285
+ end
286
+
287
+ end
@@ -0,0 +1,118 @@
1
+ # Parse a Fortran 95 file.
2
+
3
+ require "rdoc/code_objects"
4
+
5
+ module RDoc
6
+
7
+ # See rdoc/parsers/parse_f95.rb
8
+
9
+ class Token
10
+
11
+ NO_TEXT = "??".freeze
12
+
13
+ def initialize(line_no, char_no)
14
+ @line_no = line_no
15
+ @char_no = char_no
16
+ @text = NO_TEXT
17
+ end
18
+ # Because we're used in contexts that expect to return a token,
19
+ # we set the text string and then return ourselves
20
+ def set_text(text)
21
+ @text = text
22
+ self
23
+ end
24
+
25
+ attr_reader :line_no, :char_no, :text
26
+
27
+ end
28
+
29
+ class Fortran95parser
30
+
31
+ extend ParserFactory
32
+ parse_files_matching(/\.(f9(0|5)|F)$/)
33
+
34
+ # prepare to parse a Fortran 95 file
35
+ def initialize(top_level, file_name, body, options)
36
+ @body = body
37
+ @options = options
38
+ @top_level = top_level
39
+ @progress = $stderr unless options.quiet
40
+ end
41
+
42
+ # devine code constructs
43
+ def scan
44
+
45
+ # modules and programs
46
+ if @body =~ /^(module|program)\s+(\w+)/i
47
+ progress "m"
48
+ f9x_module = @top_level.add_module NormalClass, $2
49
+ f9x_module.record_location @top_level
50
+ first_comment, second_comment = $`.gsub(/^!\s?/,"").split "\n\s*\n"
51
+ if second_comment
52
+ @top_level.comment = first_comment if first_comment
53
+ f9x_module.comment = second_comment
54
+ else
55
+ f9x_module.comment = first_comment if first_comment
56
+ end
57
+ end
58
+
59
+ # use modules
60
+ remaining_code = @body
61
+ while remaining_code =~ /^\s*use\s+(\w+)/i
62
+ remaining_code = $~.post_match
63
+ progress "."
64
+ f9x_module.add_include Include.new($1, "") if f9x_module
65
+ end
66
+
67
+ # subroutines
68
+ remaining_code = @body
69
+ while remaining_code =~ /^\s*subroutine\s+(\w+)\s*\((.*?)\)/im
70
+ remaining_code = $~.post_match
71
+ subroutine = AnyMethod.new("Text", $1)
72
+ subroutine.singleton = false
73
+
74
+ prematchText = $~.pre_match
75
+ params = $2
76
+ params.gsub!(/&/,'')
77
+ subroutine.params = params
78
+ comment = find_comments prematchText
79
+ subroutine.comment = comment if comment
80
+
81
+ subroutine.start_collecting_tokens
82
+ remaining_code =~ /^\s*end\s+subroutine/i
83
+ code = "subroutine #{subroutine.name} (#{subroutine.params})\n"
84
+ code += $~.pre_match
85
+ code += "\nend subroutine\n"
86
+ subroutine.add_token Token.new(1,1).set_text(code)
87
+
88
+ progress "s"
89
+ f9x_module.add_method subroutine if f9x_module
90
+ end
91
+
92
+ @top_level
93
+
94
+ end
95
+
96
+ def find_comments text
97
+ lines = text.split("\n").reverse
98
+ comment_block = Array.new
99
+ lines.each do |line|
100
+ break if line =~ /^\s*\w/
101
+ comment_block.unshift line.sub(/^!\s?/,"")
102
+ end
103
+ nice_lines = comment_block.join("\n").split "\n\s*\n"
104
+ nice_lines.shift
105
+ nice_lines.shift
106
+ nice_lines.shift
107
+ end
108
+
109
+ def progress(char)
110
+ unless @options.quiet
111
+ @progress.print(char)
112
+ @progress.flush
113
+ end
114
+ end
115
+
116
+ end # class Fortran95parser
117
+
118
+ end # module RDoc