Extractor.pm
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:5k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. package Extractor;
  2. use strict;
  3. use warnings;
  4. our %modules;
  5. our %functions;
  6. our %classes;
  7. sub error {
  8. print STDERR "** Error: @_";
  9. }
  10. sub initItem {
  11. my $item = shift;
  12. $item->{params} = [];
  13. $item->{name} = '';
  14. $item->{desc} = '';
  15. $item->{example} = '';
  16. $item->{requires} = '';
  17. $item->{ensures} = '';
  18. $item->{returns} = '';
  19. $item->{invariant} = '';
  20. $item->{throws} = '';
  21. $item->{isVar} = 0;
  22. # $item->{param_declaration}
  23. # $item->{type}
  24. # $item->{visibility}
  25. }
  26. # Extractor::addModule(file, package)
  27. # Extract documentation from a Perl module.
  28. sub addModule {
  29. my ($file, $package) = @_;
  30. if (!open(F, "< $file")) {
  31. error "Unable to open $file for reading.n";
  32. return 0;
  33. }
  34. binmode F;
  35. my $linenum = 0;
  36. my $state = 'ready';
  37. my %module = (
  38. package => $package,
  39. name => '',
  40. desc => '',
  41. items => {},
  42. categories => {},
  43. file => $file
  44. );
  45. my %item;
  46. my $category = '';
  47. initItem(%item);
  48. foreach my $line (<F>) {
  49. $linenum++;
  50. $line =~ s/r//g;
  51. if ($line =~ /^package (.*);$/) {
  52. $classes{$1} = $package;
  53. next;
  54. } elsif ($line !~ /^#/) {
  55. if ($state =~ /^function-/ && $item{name} ne '') {
  56. # The end of a function description has been reached
  57. my %copy = %item;
  58. $copy{desc} =~ s/n+$//s;
  59. $copy{example} =~ s/n+$//s;
  60. $copy{package} = $package;
  61. $copy{category} = $category;
  62. $module{items}{$copy{name}} = %copy;
  63. $module{categories}{$category}{$copy{name}} = %copy;
  64. $functions{$copy{name}} = %copy;
  65. }
  66. %item = ();
  67. initItem(%item);
  68. $state = 'ready';
  69. next;
  70. }
  71. if ($state eq 'ready') {
  72. # Ready to accept the beginning of documentation comments.
  73. # Look for lines that start with '##'.
  74. if ($line eq "##n") {
  75. $state = 'start';
  76. } elsif ($line =~ /^### CATEGORY: (.+)$/) {
  77. $category = $1;
  78. $state = 'category';
  79. }
  80. } elsif ($state eq 'start') {
  81. # Reading first line of a documentation comment.
  82. if ($line =~ /^# MODULE DESCRIPTION: (.+)/) {
  83. # This comment block is a module description
  84. $module{name} = $1 if ($1);
  85. $state = 'module-description';
  86. } else {
  87. # This is a function, variable or hash field description.
  88. my $def;
  89. # Check whether the declaration is abstract.
  90. $line =~ s/^# //;
  91. if ($line =~ /^abstract /) {
  92. $item{abstract} = 1;
  93. $line =~ s/^abstract //;
  94. }
  95. # Check whether a type is defined.
  96. if ($line =~ /^([a-z0-9_:*<>]+) (.+)$/i) {
  97. # Typed
  98. $def = $2;
  99. $item{type} = $1;
  100. } else {
  101. # Not typed
  102. $def = $line;
  103. $def =~ s/n//;
  104. }
  105. if ($def =~ /(.*)/) {
  106. # Function
  107. ($item{name}, $item{param_declaration}) = $def =~ /^(.*?)((.*))$/;
  108. } else {
  109. # Variable or hash field
  110. $item{name} = $def;
  111. $item{isVar} = 1;
  112. $item{param_declaration} = '';
  113. }
  114. $state = 'function-params';
  115. }
  116. } elsif ($state eq 'module-description') {
  117. $line =~ s/^# ?//;
  118. next if ($line eq "n" && length($module{desc}) == 0);
  119. $module{desc} .= $line;
  120. } elsif ($state eq 'function-params') {
  121. $line =~ s/^# ?//;
  122. if ($line eq "n") {
  123. # We have reached an empty line. This means there
  124. # are no parameter descriptions left to read.
  125. # The next line is the function description.
  126. $state = 'function-description';
  127. # The "Returns", "Requires", "Ensures", "Invariant"
  128. # and "Throws" parameters deserve special treatment.
  129. my @newParams;
  130. foreach my $param (@{$item{params}}) {
  131. if ($param->[0] eq 'Returns') {
  132. $item{returns} = $param->[1];
  133. } elsif ($param->[0] eq 'Requires') {
  134. $item{requires} = $param->[1];
  135. } elsif ($param->[0] eq 'Ensures') {
  136. $item{ensures} = $param->[1];
  137. } elsif ($param->[0] eq 'Invariant') {
  138. $item{invariant} = $param->[1];
  139. } elsif ($param->[0] eq 'Throws') {
  140. $item{throws} = $param->[1];
  141. } else {
  142. push @newParams, $param;
  143. }
  144. }
  145. $item{params} = @newParams;
  146. } else {
  147. # Process parameter
  148. $line =~ s/n//;
  149. if (index($line, ':') == -1) {
  150. # A ':' character is missing.
  151. if (@{$item{params}} == 0) {
  152. # This is an invalid parameter description.
  153. error ""$line" ($file line $linenum) is not a valid parameter description.n";
  154. } else {
  155. # This is part of the previous parameter description.
  156. $item{params}[$#{$item{params}}][1] .= $line;
  157. }
  158. next;
  159. }
  160. my ($param, $desc) = split(/ *: */, $line, 2);
  161. push @{$item{params}}, [$param, $desc];
  162. }
  163. } elsif ($state eq 'function-description') {
  164. $line =~ s/^# ?//;
  165. next if ($line eq "n" && length($item{desc}) == 0);
  166. if ($line eq "Example:n") {
  167. $state = 'function-example';
  168. next;
  169. }
  170. $item{desc} .= $line;
  171. } elsif ($state eq 'function-example') {
  172. $line =~ s/^# ?//;
  173. $item{example} .= $line;
  174. }
  175. }
  176. close(F);
  177. $modules{$package} = %module;
  178. return 1;
  179. }
  180. 1;