root/trunk/idldoc/src/parser/docparidldocformatparser__define.pro @ 213

Revision 213, 15.6 KB (checked in by mgalloy, 6 years ago)

Displaying properties.

Line 
1; docformat = 'rst'
2
3;+
4; Handles parsing of IDLdoc syntax comment blocks.
5;-
6
7
8;+
9; Removes leading blank lines from string arrays.
10;
11; :Params:
12;    lines : in, out, required, type=strarr
13;       line from which to remove leading blank lines
14;-
15pro docparidldocformatparser::_removeSpace, lines
16  compile_opt strictarr
17
18  ; line is all space
19  re = '^[[:space:]]*$'
20 
21  ; stop at first line that is not all space
22  i = 0
23  while (i lt n_elements(lines) && stregex(lines[i], re, /boolean) eq 1) do i++
24 
25  ; return empty string if no lines left
26  lines = i lt n_elements(lines) ? lines[i:*] : ''
27end
28
29
30;+
31; Parse the lines from a tag.
32;
33; :Params:
34;    `lines` : in, out, required, type=strarr
35;
36; :Keywords:
37;    has_argument : in, optional, type=boolean
38;    has_attributes : in, optional, type=boolean
39;    tag : out, optional, type=string
40;    argument : out, optional, type=string
41;    n_attributes : out, optional, type=long
42;    attributes : out, optional, type=strarr
43;-
44function docparidldocformatparser::_parseTag, lines, $
45                                              has_argument=hasArgument, $
46                                              tag=tag, argument=argument, $
47                                              n_attributes=nAttributes, $
48                                              attribute_names=attributeNames, $
49                                              attribute_values=attributeValues
50  compile_opt strictarr
51 
52  myLines = lines
53 
54  ; find tag
55  re = '^[[:space:]]*@([[:alpha:]_]+)'
56  tagStart = stregex(myLines[0], re, length=tagLength, /subexpr)
57  if (tagStart[0] lt 0) then begin
58    self.system->warning, 'invalid syntax: ' + myLines[0]
59    return, ''
60  endif
61  tag = strmid(myLines[0], tagStart[1], tagLength[1])
62  myLines[0] = strmid(myLines[0], tagStart[1] + tagLength[1])
63 
64  if (~keyword_set(hasArgument)) then return, myLines
65 
66  ; find argument
67 
68  self->_removeSpace, myLines
69 
70  re = '^[[:space:]]*([[:alnum:]_$]+)'
71  argStart = stregex(myLines[0], re, length=argLength, /subexpr)
72  ; if argStart[0] eq -1 then ERROR
73  argument = strmid(myLines[0], argStart[1], argLength[1])
74  myLines[0] = strmid(myLines[0], argStart[1] + argLength[1])
75 
76  ; find attributes
77
78  attributeNamesList = obj_new('MGcoArrayList', type=7)
79  attributeValuesList = obj_new('MGcoArrayList', type=7)
80 
81  re = '^[[:space:]]*{([^}]*)}.*'
82  starts = 0
83  while (starts[0] ge 0) do begin
84    self->_removeSpace, myLines
85    starts = stregex(myLines[0], re, /subexpr, length=lengths)
86    attribute = strmid(myLines[0], starts[1], lengths[1])
87    myLines[0] = strmid(myLines[0], starts[1] + lengths[1] + 1L)
88    if (starts[0] ge 0) then begin
89      equalPos = strpos(attribute, '=')
90      if (equalPos ge 0) then begin
91        attributeNamesList->add, strmid(attribute, 0L, equalPos)
92        attributeValuesList->add, strmid(attribute, equalPos + 1L)
93      endif else begin
94        attributeNamesList->add, attribute
95        attributeValuesList->add, ''
96      endelse
97    endif
98  endwhile
99 
100  ; return attribute information
101  nAttributes = attributeNamesList->count()
102  if (nAttributes gt 0) then begin
103    attributeNames = attributeNamesList->get(/all)
104    attributeValues = attributeValuesList->get(/all)   
105  endif
106 
107  obj_destroy, [attributeNamesList, attributeValuesList]
108 
109  return, myLines
110end
111
112
113;+
114; Handles a tag with attributes (i.e. {} enclosed arguments like in param or
115; keyword).
116;
117; :Params:
118;    `lines` : in, required, type=strarr
119;       lines of raw text for that tag
120; :Keywords:
121;    `routine` : in, required, type=object
122;       routine tree object
123;    `markup_parser` : in, required, type=object
124;       markup parser object
125;-
126pro docparidldocformatparser::_handleArgumentTag, lines, $
127                                                  routine=routine, $
128                                                  markup_parser=markupParser
129  compile_opt strictarr
130 
131  lines = self->_parseTag(lines, /has_argument, $
132                          tag=tag, argument=argument, $
133                          n_attributes=nAttributes, $
134                          attribute_names=attributeNames, $
135                          attribute_values=attributeValues)
136 
137  case strlowcase(tag) of
138    'param': arg = routine->getParameter(argument, found=found)
139    'keyword': arg = routine->getKeyword(argument, found=found)
140    else:   ; shouldn't happen
141  endcase
142 
143  routine->getProperty, name=routineName
144  if (~found) then begin
145    self.system->warning, strlowcase(tag) + ' ' + argument $
146                            + ' not found in ' + routineName
147    return
148  endif
149
150  for i = 0L, nAttributes - 1L do begin
151    case strlowcase(attributeNames[i]) of
152      'in': arg->setProperty, is_input=1
153      'out': arg->setProperty, is_output=1
154      'optional': arg->setProperty, is_optional=1
155      'required': arg->setProperty, is_required=1
156      'private': arg->setProperty, is_private=1
157      'hidden': arg->setProperty, is_hidden=1
158      'obsolete': arg->setProperty, is_obsolete=1
159
160      'type': arg->setProperty, type=attributeValues[i]
161      'default': arg->setProperty, default_value=attributeValues[i]
162      else: begin
163          self.system->warning, $
164            'unknown argument attribute ' + attributeNames[i] $
165              + ' for argument' + argument + ' in ' + routineName           
166        end
167    endcase
168  endfor
169 
170  comments = markupParser->parse(lines)
171  arg->setProperty, comments=comments
172end
173
174
175;+
176; Handles one tag.
177;
178; :Params:
179;    `tag` : in, required, type=string
180;       rst tag, i.e. returns, params, keywords, etc.
181;    `lines` : in, required, type=strarr
182;       lines of raw text for that tag
183; :Keywords:
184;    `routine` : in, required, type=object
185;       routine tree object
186;    `markup_parser` : in, required, type=object
187;       markup parser object
188;-
189pro docparidldocformatparser::_handleRoutineTag, tag, lines, $
190                                                 routine=routine,  $
191                                                 markup_parser=markupParser
192  compile_opt strictarr
193 
194  ; TODO: finish this
195 
196  case strlowcase(tag) of
197    'abstract': routine->setProperty, is_abstract=1B
198    'author': routine->setProperty, author=markupParser->parse(self->_parseTag(lines))
199    'bugs': routine->setProperty, bugs=markupParser->parse(self->parseTag(lines))     
200    'categories':
201    'copyright': routine->setProperty, copyright=markupParser->parse(self->_parseTag(lines))
202    'customer_id': routine->setProperty, customer_id=markupParser->parse(self->_parseTag(lines))
203    'examples': routine->setProperty, examples=markupParser->parse(self->_parseTag(lines))
204    'field':
205    'file_comments': begin
206        routine->getProperty, file=file
207        file->setProperty, comments=markupParser->parse(self->_parseTag(lines))
208      end
209    'hidden': routine->setProperty, is_hidden=1
210    'hidden_file': begin
211        routine->getProperty, file=file
212        file->setProperty, is_hidden=1B
213      end
214    'history': routine->setProperty, history=markupParser->parse(self->_parseTag(lines))
215    'inherits':
216    'keyword': self->_handleArgumentTag, lines, routine=routine, markup_parser=markupParser
217    'obsolete': routine->setProperty, is_obsolete=1B
218    'param': self->_handleArgumentTag, lines, routine=routine, markup_parser=markupParser
219    'post': routine->setProperty, post=markupParser->parse(self->_parseTag(lines))
220    'pre': routine->setProperty, pre=markupParser->parse(self->_parseTag(lines))
221    'private': routine->setProperty, is_private=1B
222    'private_file': begin
223        routine->getProperty, file=file
224        file->setProperty, is_private=1B
225      end
226    'requires':
227    'restrictions': routine->setProperty, restrictions=markupParser->parse(self->_parseTag(lines))
228    'returns': routine->setProperty, returns=markupParser->parse(self->_parseTag(lines))
229    'todo': routine->setProperty, todo=markupParser->parse(self->_parseTag(lines))
230    'uses':
231    'version': routine->setProperty, version=markupParser->parse(self->_parseTag(lines))
232    else: begin
233        routine->getProperty, name=name
234        self.system->warning, 'unknown tag ' + tag + ' in routine ' + name
235      end
236  endcase
237end
238
239
240;+
241; Handles one tag.
242;
243; :Params:
244;    `tag` : in, required, type=string
245;       rst tag, i.e. returns, params, keywords, etc.
246;    `lines` : in, required, type=strarr
247;       lines of raw text for that tag
248; :Keywords:
249;    `file` : in, required, type=object
250;       file tree object
251;    `markup_parser` : in, required, type=object
252;       markup parser object
253;-
254pro docparidldocformatparser::_handleFileTag, tag, lines, $
255                                              file=file, $
256                                              markup_parser=markupParser
257  compile_opt strictarr
258 
259  case strlowcase(tag) of
260    'property': begin
261        file->getProperty, is_class=isClass, class=class
262        if (~isClass) then begin
263          self.system->warning, 'property not allowed non-class definition file'
264        endif
265   
266        comments = self->_parseTag(lines, /has_argument, $
267                                   argument=propertyName, $
268                                   n_attributes=nAttributes, $
269                                   attribute_names=attributeNames, $
270                                   attribute_values=attributeValues)     
271                                   
272        ; TODO: ready to add property
273        ; create property object? lookup property object?
274        ;   should all possible properties be created (i.e. from getProperty,
275        ;   setProperty, and init methods)? 
276        ; get attributes to set is_get, is_set, is_init
277        ; set comments 
278        property = obj_new('DOCtreeProperty', propertyName, $
279                                              system=self.system, class=class)
280        property->setProperty, comments=markupParser->parse(comments)
281       
282        class->addProperty, property
283      end
284   
285    'hidden': file->setProperty, is_hidden=1B
286    'private': file->setProperty, is_private=1B
287   
288    'examples': file->setProperty, examples=markupParser->parse(self->_parseTag(lines))
289   
290    'author': file->setProperty, author=markupParser->parse(self->_parseTag(lines))
291    'copyright': file->setProperty, copyright=markupParser->parse(self->_parseTag(lines))
292    'history': file->setProperty, history=markupParser->parse(self->_parseTag(lines))
293    'version': file->setProperty, version=markupParser->parse(self->_parseTag(lines))
294    else: begin
295        file->getProperty, basename=basename
296        self.system->warning, 'unknown tag ' + tag + ' in file ' + basename
297      end
298  endcase
299end
300
301
302;+
303; Handles parsing of a comment block associated with a routine using IDLdoc
304; syntax.
305;
306; :Params:
307;    `lines` : in, required, type=strarr
308;       all lines of the comment block
309; :Keywords:
310;    `routine` : in, required, type=object
311;       routine tree object
312;    `markup_parser` : in, required, type=object
313;       markup parser object
314;-
315pro docparidldocformatparser::parseRoutineComments, lines, routine=routine, $
316                                                    markup_parser=markupParser
317  compile_opt strictarr
318
319  ; find @ symbols that are the first non-whitespace character on the line
320  tagLocations = where(stregex(lines, '^[[:space:]]*@') ne -1, nTags)
321 
322  ; parse normal comments
323  tagsStart = nTags gt 0 ? tagLocations[0] : n_elements(lines)
324  if (tagsStart ne 0) then begin
325    comments = markupParser->parse(lines[0:tagsStart - 1L])
326    routine->setProperty, comments=comments
327  endif
328
329  ; go through each tag
330  for t = 0L, nTags - 1L do begin
331    tagStart = tagLocations[t]
332    tag = strmid(stregex(lines[tagStart], '@[[:alpha:]_]+', /extract), 1)
333    tagEnd = t eq nTags - 1L $
334               ? n_elements(lines) - 1L $
335               : tagLocations[t + 1L] - 1L
336    self->_handleRoutineTag, tag, lines[tagStart:tagEnd], $
337                             routine=routine, markup_parser=markupParser
338  endfor
339end
340
341
342;+
343; Handles parsing of a comment block associated with a file using IDLdoc syntax.
344;
345; :Params:
346;    `lines` : in, required, type=strarr
347;       all lines of the comment block
348; :Keywords:
349;    `file` : in, required, type=object
350;       file tree object
351;    `markup_parser` : in, required, type=object
352;       markup parser object
353;-
354pro docparidldocformatparser::parseFileComments, lines, file=file, $
355                                                 markup_parser=markupParser                         
356  compile_opt strictarr
357 
358  ; find @ symbols that are the first non-whitespace character on the line
359  tagLocations = where(stregex(lines, '^[[:space:]]*@') ne -1, nTags)
360 
361  ; parse normal comments
362  tagsStart = nTags gt 0 ? tagLocations[0] : n_elements(lines)
363  if (tagsStart ne 0) then begin
364    comments = markupParser->parse(lines[0:tagsStart - 1L])
365    file->setProperty, comments=comments
366  endif
367
368  ; go through each tag
369  for t = 0L, nTags - 1L do begin
370    tagStart = tagLocations[t]
371    tag = strmid(stregex(lines[tagStart], '@[[:alpha:]_]+', /extract), 1)
372    tagEnd = t eq nTags - 1L $
373               ? n_elements(lines) - 1L $
374               : tagLocations[t + 1L] - 1L
375    self->_handleFileTag, tag, lines[tagStart:tagEnd], $
376                          file=file, markup_parser=markupParser
377  endfor
378end
379
380
381;+
382; Handles parsing of a comment block in the overview file using IDLdoc syntax.
383;
384; :Params:
385;    `lines` : in, required, type=strarr
386;       all lines of the comment block
387; :Keywords:
388;    `system` : in, required, type=object
389;       system object
390;    `markup_parser` : in, required, type=object
391;       markup parser object
392;-
393pro docparidldocformatparser::parseOverviewComments, lines, system=system, $
394                                                     markup_parser=markupParser
395  compile_opt strictarr
396
397  ; find @ symbols that are the first non-whitespace character on the line
398  tagLocations = where(stregex(lines, '^[[:space:]]*@') ne -1, nTags)
399 
400  ; parse normal comments
401  tagsStart = nTags gt 0 ? tagLocations[0] : n_elements(lines)
402  if (tagsStart ne 0) then begin
403    comments = markupParser->parse(lines[0:tagsStart - 1L])
404    system->setProperty, overview_comments=comments
405  endif
406
407  ; go through each tag
408  for t = 0L, nTags - 1L do begin
409    tagStart = tagLocations[t]
410    tag = strmid(stregex(lines[tagStart], '@[[:alpha:]_]+', /extract), 1)
411    tagEnd = t eq nTags - 1L $
412               ? n_elements(lines) - 1L $
413               : tagLocations[t + 1L] - 1L
414    tagLines = self->_parseTag(lines[tagStart:tagEnd])
415   
416    case strlowcase(tag) of
417      'dir': begin
418          re = '^[[:space:]]*([[:alpha:]._$\-\/]+)[[:space:]]+'
419          argStart = stregex(tagLines[0], re, /subexpr, length=argLength)
420          if (argStart[0] eq -1L) then begin
421            system->getProperty, overview=overview
422            system->warning, 'directory argument not present for dir tag in overview file ' + overview
423            break           
424          endif
425         
426          dirName = strmid(tagLines[0], argStart[1], argLength[1])
427          tagLines[0] = strmid(tagLines[0], argStart[1] + argLength[1])
428         
429          system->getProperty, directories=directories
430          for d = 0L, directories->count() - 1L do begin
431            dir = directories->get(position=d)
432            dir->getProperty, location=location
433            if (dirName eq location) then begin
434              tree = markupParser->parse(tagLines)
435              dir->setProperty, overview_comments=tree
436              break
437            endif
438          endfor
439        end
440      else: begin
441          system->getProperty, overview=overview
442          system->warning, 'unknown tag ' + tag + ' in overview file ' + overview
443        end
444    endcase
445  endfor
446end
447
448
449;+
450; Define instance variables.
451;-
452pro docparidldocformatparser__define
453  compile_opt strictarr
454
455  define = { DOCparIDLdocFormatParser, inherits DOCparFormatParser }
456end
Note: See TracBrowser for help on using the browser.