cgialib 0.0.1 → 0.0.2
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.
- data/Manifest.txt +7 -2
- data/Rakefile +4 -3
- data/examples/ut/mytest1.c +22 -0
- data/features/language_parser.feature +21 -0
- data/features/steps/language_parser.rb +84 -0
- data/lib/cgialib/lp/JavaDoc.rb +220 -0
- data/lib/cgialib/lp/JavaLanguageScanner.rb +660 -0
- data/lib/cgialib/lp/SQLLanguageScanner.rb +688 -0
- data/lib/cgialib/lp/SQLTokenizer.rb +403 -0
- data/lib/cgialib/lp.rb +5 -0
- data/lib/cgialib/template/ut/c.rb +10 -3
- data/lib/cgialib.rb +1 -1
- data/website/index.html +4 -21
- data/website/index.txt +2 -27
- data/website/template.html.erb +1 -1
- metadata +29 -4
- data/features/development.feature +0 -13
- data/features/steps/common.rb +0 -174
@@ -0,0 +1,660 @@
|
|
1
|
+
# File: JavaLanguageScanner.rb
|
2
|
+
# Author: Jack Herrington
|
3
|
+
# Purpose: The JavaLanguageScanner object specialized to read Java token streams (from Java files)
|
4
|
+
# Date: 12/21/02
|
5
|
+
|
6
|
+
#require "Tokenizer"
|
7
|
+
#require "Language"
|
8
|
+
#require "JavaDoc"
|
9
|
+
|
10
|
+
module LanguageParser
|
11
|
+
# class : JavaVariable
|
12
|
+
#
|
13
|
+
# A specialized ClassVariable that includes the JavaDoc for the class
|
14
|
+
|
15
|
+
class JavaVariable < ClassVariable
|
16
|
+
|
17
|
+
# initialize()
|
18
|
+
#
|
19
|
+
# Constructor
|
20
|
+
|
21
|
+
def initialize()
|
22
|
+
|
23
|
+
super()
|
24
|
+
|
25
|
+
@javadoc = nil
|
26
|
+
@javadocClass = JavaDoc
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :javadoc # The JavaDoc object
|
31
|
+
|
32
|
+
attr_accessor :javadocClass # The class to use to creat the JavaDoc object
|
33
|
+
|
34
|
+
# comment=( text )
|
35
|
+
#
|
36
|
+
# text - The comment text
|
37
|
+
#
|
38
|
+
# Override of the comment set method to not only set the comment but also
|
39
|
+
# to parse it into the JavaDoc
|
40
|
+
|
41
|
+
def comment=( text )
|
42
|
+
|
43
|
+
super( text )
|
44
|
+
|
45
|
+
@javadoc = @javadocClass.new() unless ( @javadoc )
|
46
|
+
@javadoc.parse( text )
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
# class : JavaClass
|
53
|
+
#
|
54
|
+
# A specialization for LanguageClass to handle the JavaDoc markup on a Java
|
55
|
+
# class declaration
|
56
|
+
|
57
|
+
class JavaClass < LanguageClass
|
58
|
+
|
59
|
+
# initialize()
|
60
|
+
#
|
61
|
+
# Constructor
|
62
|
+
|
63
|
+
def initialize()
|
64
|
+
|
65
|
+
super()
|
66
|
+
|
67
|
+
@javadoc = nil
|
68
|
+
@javadocClass = JavaDoc
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
attr_reader :javadoc # The JavaDoc attached to the class
|
73
|
+
|
74
|
+
attr_accessor :javadocClass # The class to use to build the JavaDoc object
|
75
|
+
|
76
|
+
# comments=( text )
|
77
|
+
#
|
78
|
+
# text - The comment text
|
79
|
+
#
|
80
|
+
# Overrides the comment text setter to build the JavaDoc as well as setting
|
81
|
+
# the comment
|
82
|
+
|
83
|
+
def comments=( text )
|
84
|
+
|
85
|
+
super( text )
|
86
|
+
|
87
|
+
@javadoc = @javadocClass.new() unless ( @javadoc )
|
88
|
+
@javadoc.parse( text )
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
# class : JavaPrototype
|
95
|
+
#
|
96
|
+
# A derived class of Prototype to account for the JavaDoc attached to the
|
97
|
+
# prototype
|
98
|
+
|
99
|
+
class JavaPrototype < Prototype
|
100
|
+
|
101
|
+
# initialize()
|
102
|
+
#
|
103
|
+
# Constructor for the class
|
104
|
+
|
105
|
+
def initialize()
|
106
|
+
|
107
|
+
super()
|
108
|
+
|
109
|
+
@javadoc = nil
|
110
|
+
@javadocClass = JavaDoc
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
attr_reader :javadoc # The JavaDoc attached to the method
|
115
|
+
|
116
|
+
attr_accessor :javadocClass # The class to build the JavaDoc object
|
117
|
+
|
118
|
+
# add_comment( text )
|
119
|
+
#
|
120
|
+
# text - The comment text
|
121
|
+
#
|
122
|
+
# Overrides the add_comment method to account for the JavaDoc as well as
|
123
|
+
# adding the comment.
|
124
|
+
|
125
|
+
def add_comment( text )
|
126
|
+
|
127
|
+
super( text )
|
128
|
+
|
129
|
+
@javadoc = @javadocClass.new() unless ( @javadoc )
|
130
|
+
@javadoc.parse( text.to_s )
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
# class : JavaLanguageScanner
|
137
|
+
#
|
138
|
+
# This is the JavaLanguageScanner specialized to read prototypes for Java
|
139
|
+
# functions.
|
140
|
+
|
141
|
+
class JavaLanguageScanner < LanguageScanner
|
142
|
+
|
143
|
+
# initialize()
|
144
|
+
#
|
145
|
+
# Constructs the C language scanner class
|
146
|
+
|
147
|
+
def initialize()
|
148
|
+
|
149
|
+
super()
|
150
|
+
|
151
|
+
@classes = []
|
152
|
+
|
153
|
+
@prototypeClass = JavaPrototype
|
154
|
+
@variableClass = JavaVariable
|
155
|
+
@classClass = JavaClass
|
156
|
+
@javadocClass = JavaDoc
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
attr_accessor :prototypeClass # The prototype class to build
|
161
|
+
|
162
|
+
attr_reader :classes # An accessor for the array of classes found
|
163
|
+
|
164
|
+
attr_accessor :javadocClass # The class to use when build JavaDoc objects
|
165
|
+
|
166
|
+
attr_accessor :variableClass # The class to use when building variables
|
167
|
+
|
168
|
+
attr_accessor :classClass # The class to use when building classes
|
169
|
+
|
170
|
+
# to_s()
|
171
|
+
#
|
172
|
+
# Pretty printer
|
173
|
+
|
174
|
+
def to_s()
|
175
|
+
|
176
|
+
text = ""
|
177
|
+
|
178
|
+
text += "Classes:\n"
|
179
|
+
|
180
|
+
@classes.each { |jclass|
|
181
|
+
|
182
|
+
text += jclass.to_s
|
183
|
+
|
184
|
+
}
|
185
|
+
|
186
|
+
text
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
# parse( tokens )
|
191
|
+
#
|
192
|
+
# tokens - An array of tokens built by a Tokenizer
|
193
|
+
#
|
194
|
+
# This method reads the stream of tokens built by a Tokenizer
|
195
|
+
# and fills the @prototypes array with the prototypes
|
196
|
+
# that are found.
|
197
|
+
|
198
|
+
def parse( tokens )
|
199
|
+
|
200
|
+
tokens.each_index { |index|
|
201
|
+
|
202
|
+
if ( tokens[ index ].to_s == "class" || tokens[ index ].to_s == "interface" )
|
203
|
+
|
204
|
+
parse_class( tokens, index )
|
205
|
+
|
206
|
+
break;
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
}
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
protected
|
215
|
+
|
216
|
+
# parse_class( tokens, start, base_class = nil )
|
217
|
+
#
|
218
|
+
# tokens - The full array of tokens in the file
|
219
|
+
# start - The start of our class definition
|
220
|
+
# base_class - The name of the base class (nil if none)
|
221
|
+
#
|
222
|
+
# Parses the class and adds it to the class list.
|
223
|
+
|
224
|
+
def parse_class( tokens, start, base_class = nil )
|
225
|
+
|
226
|
+
# Build the class and add it
|
227
|
+
|
228
|
+
class_data = build_class()
|
229
|
+
class_data.javadocClass = @javadocClass
|
230
|
+
@classes.push( class_data )
|
231
|
+
|
232
|
+
# Backtrack to get the class comment
|
233
|
+
|
234
|
+
index = start
|
235
|
+
while( index >= 0 )
|
236
|
+
|
237
|
+
break if ( tokens[ index ].to_s == "public" )
|
238
|
+
break if ( tokens[ index ].to_s == "private" )
|
239
|
+
break if ( tokens[ index ].to_s == "class" )
|
240
|
+
|
241
|
+
index -= 1
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
# Add the comments to the class
|
246
|
+
|
247
|
+
comment = tokens.get_comments( index )
|
248
|
+
class_data.comments = comment
|
249
|
+
class_data.comments.strip!
|
250
|
+
|
251
|
+
# Make sure the name is set to nil, we use nil as a marker in the state
|
252
|
+
# machine
|
253
|
+
|
254
|
+
class_data.name = nil
|
255
|
+
|
256
|
+
# This is the code fragment leading up to the interior
|
257
|
+
# of the function
|
258
|
+
|
259
|
+
codefrag = TokenStream.new
|
260
|
+
|
261
|
+
# 'level' is the level of bracket nesting.
|
262
|
+
|
263
|
+
level = 0
|
264
|
+
|
265
|
+
# This will be true if we are looking at precompiler tokens
|
266
|
+
|
267
|
+
hold_until_return = false
|
268
|
+
|
269
|
+
# Look through each token
|
270
|
+
|
271
|
+
index = start
|
272
|
+
|
273
|
+
while( index < tokens.length )
|
274
|
+
|
275
|
+
tok = tokens[ index ]
|
276
|
+
|
277
|
+
# Handles parsing the class name
|
278
|
+
|
279
|
+
if ( class_data.name == nil && tok.is_a?( CodeToken ) && tok.to_s != "class" )
|
280
|
+
|
281
|
+
class_name = tok.to_s
|
282
|
+
|
283
|
+
class_name = "#{base_class}.#{class_name}" if ( base_class )
|
284
|
+
|
285
|
+
class_data.name = class_name
|
286
|
+
class_data.type = tokens[ start ].to_s
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
# Handles parsing the parents of the class
|
291
|
+
|
292
|
+
if ( level == 0 && tok.is_a?( CodeToken ) && class_data.name != nil )
|
293
|
+
|
294
|
+
if ( tok.to_s != "{" && tok.to_s != class_data.name &&
|
295
|
+
tok.to_s != "implements" && tok.to_s != "extends" )
|
296
|
+
|
297
|
+
class_data.add_parent( tok.to_s )
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
302
|
+
|
303
|
+
# For imports we wait until a return
|
304
|
+
|
305
|
+
if ( hold_until_return )
|
306
|
+
|
307
|
+
hold_until_return = false if ( tok.to_s =~ /^\n/ )
|
308
|
+
next
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
if tok.to_s == "class" || tok.to_s == "interface"
|
313
|
+
|
314
|
+
# Waiting for the class name
|
315
|
+
|
316
|
+
index = parse_class( tokens, index, class_data.name ) if ( index != start )
|
317
|
+
|
318
|
+
codefrag = TokenStream.new()
|
319
|
+
|
320
|
+
elsif tok.to_s == "{"
|
321
|
+
|
322
|
+
# If we are at level zero then we are
|
323
|
+
# opening a function for code, so we
|
324
|
+
# should interpret what we have
|
325
|
+
# up until now.
|
326
|
+
|
327
|
+
if level == 1
|
328
|
+
|
329
|
+
parse_prototype( class_data, codefrag )
|
330
|
+
|
331
|
+
codefrag = TokenStream.new()
|
332
|
+
|
333
|
+
end
|
334
|
+
|
335
|
+
# Now increment the level
|
336
|
+
|
337
|
+
level += 1
|
338
|
+
|
339
|
+
elsif tok.to_s == "}"
|
340
|
+
|
341
|
+
# Decrement the level
|
342
|
+
|
343
|
+
level -= 1
|
344
|
+
|
345
|
+
break if ( level == 0 )
|
346
|
+
|
347
|
+
elsif tok.to_s == ";"
|
348
|
+
|
349
|
+
# If we see a ";" and we are at level
|
350
|
+
# zero then we have a constant
|
351
|
+
# declaration
|
352
|
+
|
353
|
+
if level == 1
|
354
|
+
|
355
|
+
parse_variable( class_data, codefrag )
|
356
|
+
|
357
|
+
codefrag = TokenStream.new()
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
|
362
|
+
else
|
363
|
+
|
364
|
+
# Otherwise push the fragment
|
365
|
+
|
366
|
+
codefrag.push( tok ) if level == 1
|
367
|
+
|
368
|
+
end
|
369
|
+
|
370
|
+
index += 1
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
index
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
# parse_declaration( codefrag )
|
379
|
+
#
|
380
|
+
# codefrag - The code token array
|
381
|
+
#
|
382
|
+
# This turns the set of tokens that represent a declaration
|
383
|
+
# ("int *a[]") into a name ("a"), a type "int *", and an
|
384
|
+
# array boolean (true).
|
385
|
+
|
386
|
+
def parse_declaration( codefrag )
|
387
|
+
|
388
|
+
# Get just the code
|
389
|
+
|
390
|
+
code = codefrag.code_only
|
391
|
+
|
392
|
+
# If we are an assignment declaration then parse that
|
393
|
+
|
394
|
+
if ( code.find( "=" ) )
|
395
|
+
|
396
|
+
value = code.pop
|
397
|
+
code.pop
|
398
|
+
|
399
|
+
end
|
400
|
+
|
401
|
+
# See if we are private, public or protected
|
402
|
+
|
403
|
+
visibility = ""
|
404
|
+
visibility = "private" if code.find_and_remove( "private" )
|
405
|
+
visibility = "public" if code.find_and_remove( "public" )
|
406
|
+
visibility = "protected" if code.find_and_remove( "protected" )
|
407
|
+
|
408
|
+
# Get the static and final values
|
409
|
+
|
410
|
+
static = code.find_and_remove( "static" )
|
411
|
+
final = code.find_and_remove( "final" )
|
412
|
+
|
413
|
+
# By default this will not be an array
|
414
|
+
|
415
|
+
array = false
|
416
|
+
|
417
|
+
# Here we are backtracking from the end to find the name
|
418
|
+
# within the declaration
|
419
|
+
|
420
|
+
while( code.length > 0 )
|
421
|
+
|
422
|
+
frag = code.last
|
423
|
+
|
424
|
+
array = true if ( frag.to_s == "[" )
|
425
|
+
|
426
|
+
break unless ( frag.to_s == "[" || frag.to_s == "]" )
|
427
|
+
|
428
|
+
code.delete_at( code.length - 1 )
|
429
|
+
|
430
|
+
end
|
431
|
+
|
432
|
+
# We assume that the name is the last non-whitespace,
|
433
|
+
# non-array token
|
434
|
+
|
435
|
+
name = code.last.to_s
|
436
|
+
|
437
|
+
code.delete_at( code.length - 1 )
|
438
|
+
|
439
|
+
# Then we build the type from the remainder
|
440
|
+
|
441
|
+
type = code.map { |tok| tok.to_s }.join( " " )
|
442
|
+
|
443
|
+
# Then we return a structure that contains the declaration
|
444
|
+
# data
|
445
|
+
|
446
|
+
return {
|
447
|
+
'name' => name,
|
448
|
+
'type' => type,
|
449
|
+
'array' => array,
|
450
|
+
'value' => value,
|
451
|
+
'visibility' => visibility,
|
452
|
+
'static' => static,
|
453
|
+
'final' => final
|
454
|
+
}
|
455
|
+
|
456
|
+
end
|
457
|
+
|
458
|
+
# parse_prototype( class_data, codefrag )
|
459
|
+
#
|
460
|
+
# class_data - The class object
|
461
|
+
# codefrag - The tokens leading up to a function definition
|
462
|
+
#
|
463
|
+
# This turns the series of tokens leading up to the function
|
464
|
+
# definition and turns it into a prototype object which it
|
465
|
+
# adds to the prototype list.
|
466
|
+
|
467
|
+
def parse_prototype( class_data, codefrag )
|
468
|
+
|
469
|
+
# This will be true when we have found the first
|
470
|
+
# code token
|
471
|
+
|
472
|
+
found_code = false
|
473
|
+
|
474
|
+
# True when our iterator is within the arguments tokens
|
475
|
+
|
476
|
+
in_arguments = false
|
477
|
+
|
478
|
+
# Start contains the tokens before the arguments
|
479
|
+
|
480
|
+
start = TokenStream.new()
|
481
|
+
|
482
|
+
# args contains the sets of arguments tokens
|
483
|
+
|
484
|
+
args = TokenStream.new()
|
485
|
+
|
486
|
+
# cur_arg contains the tokens of the argument
|
487
|
+
# currently being parsed
|
488
|
+
|
489
|
+
cur_arg = TokenStream.new()
|
490
|
+
|
491
|
+
# Contains any comments found within the tokens
|
492
|
+
|
493
|
+
comments = TokenStream.new()
|
494
|
+
|
495
|
+
# Iterate through the codefrag tokens
|
496
|
+
|
497
|
+
codefrag.each { |tok|
|
498
|
+
|
499
|
+
# Set found_code to true when we find a CodeToken
|
500
|
+
|
501
|
+
found_code = true if ( tok.is_a?( CodeToken ) )
|
502
|
+
|
503
|
+
# Add the comment if the token is a comment
|
504
|
+
|
505
|
+
if tok.is_a?( CommentToken )
|
506
|
+
|
507
|
+
comments.push( tok.to_s() )
|
508
|
+
next
|
509
|
+
|
510
|
+
end
|
511
|
+
|
512
|
+
# Go to the next token if we have not found code
|
513
|
+
|
514
|
+
next unless ( found_code )
|
515
|
+
|
516
|
+
if tok.to_s == "("
|
517
|
+
|
518
|
+
# Look for the start of the arguments
|
519
|
+
|
520
|
+
in_arguments = true
|
521
|
+
cur_arg = TokenStream.new()
|
522
|
+
|
523
|
+
elsif tok.to_s == ")"
|
524
|
+
|
525
|
+
# Look for the end of the arguments, when
|
526
|
+
# we find it we dump out of the iterator
|
527
|
+
|
528
|
+
args.push( cur_arg ) if cur_arg.length > 0
|
529
|
+
cur_arg = TokenStream.new()
|
530
|
+
break
|
531
|
+
|
532
|
+
elsif in_arguments == false
|
533
|
+
|
534
|
+
# If we are not in the arguments then
|
535
|
+
# push these code tokens into the start
|
536
|
+
# fragment list
|
537
|
+
|
538
|
+
start.push( tok )
|
539
|
+
|
540
|
+
else
|
541
|
+
|
542
|
+
# We are in the arguments, so look for
|
543
|
+
# the comments that seperate the arguments
|
544
|
+
|
545
|
+
if tok.to_s == ","
|
546
|
+
|
547
|
+
args.push( cur_arg ) if cur_arg.length > 0
|
548
|
+
cur_arg = TokenStream.new()
|
549
|
+
|
550
|
+
else
|
551
|
+
|
552
|
+
cur_arg.push( tok )
|
553
|
+
|
554
|
+
end
|
555
|
+
|
556
|
+
end
|
557
|
+
|
558
|
+
}
|
559
|
+
|
560
|
+
# Have the base class build the new prototype
|
561
|
+
|
562
|
+
proto = build_prototype()
|
563
|
+
proto.javadocClass = @javadocClass
|
564
|
+
|
565
|
+
# Parse the starting declaration and set the prototype
|
566
|
+
|
567
|
+
start_decl = parse_declaration( start )
|
568
|
+
|
569
|
+
proto.class_name = class_data.name
|
570
|
+
proto.method_name = start_decl['name']
|
571
|
+
proto.method_type = start_decl['type']
|
572
|
+
proto.static = start_decl['static']
|
573
|
+
proto.visibility = start_decl['visibility']
|
574
|
+
|
575
|
+
# Parse the arguments and add them to the prototype
|
576
|
+
|
577
|
+
args.each { |arg|
|
578
|
+
|
579
|
+
arg_decl = parse_declaration( arg )
|
580
|
+
|
581
|
+
proto.add_argument( arg_decl[ 'name' ], arg_decl['type'] )
|
582
|
+
|
583
|
+
}
|
584
|
+
|
585
|
+
# Add the comments
|
586
|
+
|
587
|
+
comments.each { |comment| proto.add_comment( comment.to_s ) }
|
588
|
+
|
589
|
+
# Add this prototype to the array of found prototypes
|
590
|
+
|
591
|
+
class_data.add_method( proto )
|
592
|
+
|
593
|
+
end
|
594
|
+
|
595
|
+
# parse_variable( class_data, codefrag )
|
596
|
+
#
|
597
|
+
# class_data - The class to which we add the variable declaration
|
598
|
+
# codefrag - The code fragmen that describes the variable
|
599
|
+
#
|
600
|
+
# Parses a variable declaration and adds it to the class
|
601
|
+
|
602
|
+
def parse_variable( class_data, codefrag )
|
603
|
+
|
604
|
+
# Get the comments
|
605
|
+
|
606
|
+
comment = codefrag.comments_only.to_s
|
607
|
+
|
608
|
+
# Get the declaration
|
609
|
+
|
610
|
+
varData = parse_declaration( codefrag )
|
611
|
+
|
612
|
+
# Build the variable object and populate it
|
613
|
+
|
614
|
+
varObj = build_variable()
|
615
|
+
varObj.javadocClass = @javadocClass
|
616
|
+
varObj.name = varData[ 'name' ]
|
617
|
+
varObj.type = varData[ 'type' ]
|
618
|
+
varObj.value = varData[ 'value' ]
|
619
|
+
varObj.visibility = varData[ 'visibility' ]
|
620
|
+
varObj.static = varData[ 'static' ]
|
621
|
+
varObj.comment = comment
|
622
|
+
|
623
|
+
# Add it to our class
|
624
|
+
|
625
|
+
class_data.add_variable( varObj )
|
626
|
+
|
627
|
+
end
|
628
|
+
|
629
|
+
# build_variable()
|
630
|
+
#
|
631
|
+
# Builds a new variable object
|
632
|
+
|
633
|
+
def build_variable()
|
634
|
+
|
635
|
+
@variableClass.new()
|
636
|
+
|
637
|
+
end
|
638
|
+
|
639
|
+
# build_class()
|
640
|
+
#
|
641
|
+
# Builds a new class object
|
642
|
+
|
643
|
+
def build_class()
|
644
|
+
|
645
|
+
@classClass.new()
|
646
|
+
|
647
|
+
end
|
648
|
+
|
649
|
+
# build_prototype()
|
650
|
+
#
|
651
|
+
# Builds and returns a prototype object
|
652
|
+
|
653
|
+
def build_prototype()
|
654
|
+
|
655
|
+
@prototypeClass.new()
|
656
|
+
|
657
|
+
end
|
658
|
+
|
659
|
+
end
|
660
|
+
end
|