src2doc.pl - Extract comments in a source file, with optional fake code generation
src2doc.pl file.js > file.cpp
or in a pipeline:
cat file.js | src2doc.pl > file.cpp
This will extract comments from a source file. All comments are extracted, though typically the ones of interest are the javadoc-style ones.
No attempt is made to parse non-comment content in the input file (though any extension module may choose to). This means that this utility could be used with a variety of source programming languages (and the source programming language could use a variety of idioms).
Any input lines which are completely white space are passed through to the output (regardless of whether inside or outside a comment).
This program may be used directly as a Doxygen filter.
In addition to normal comment extraction, it also looks for special comments that start with "//:". These are interpreted as directives for code generation.
The idea is that this can be used to put code in the output that may not even be the same programming language as the input (but may be processed by a javadoc-like program in the output pipeline).
At the moment, the only output programming language supported is C++. (This is in part because C++ is the default language expected by doxygen, and currently doxygen only changes that language expectation according to file suffix, which is awkward in a pipeline/filtering setup. Also, C++ supports more paradigms than Java.)
We do document here what the output would be if we were generating Java.
The supported generation directives fall into these categories:
namespace class interface global enum
Note that in some output languages, not all of these entities are available, but we attempt to make meaningful approximations. For example, C++ has no "interface", and Java has no "enum".
example javascript input:
/** this namespace does trigonometry */ //:NSBEGIN Trigonemtry var Trigonometry = {};
/** ratio of circumference to diameter */ //:NSCONSTANT Number PI = 3.14159 Trigonometry.PI = 3.14159;
/** array of figures created */ //:NSVAR Array figures Trigonometry.figures = [];
/** calculate the area of a circle */ //:NSFUNCTION Number calculateArea(Number radius) Trigonometry.calculateArea = function(radius) {return 2 * Trigonometry.PI * radius};
//:NSEND
another (equivalent) example javascript input, with identical comments:
/** this namespace does trigonometry */ //:NSBEGIN Trigonemtry var Trigonometry = { /** ratio of circumference to diameter */ //:NSCONSTANT Number PI = 3.14159 PI: 3.14159, /** array of figures created */ //:NSVAR Array figures figures: [], /** calculate the area of a circle */ //:NSFUNCTION Number calculateArea(Number radius) calculateArea: function(radius) {return 2 * Trigonometry.PI * radius} //:NSEND };
example C++ output:
/** this namespace does trigonometry */ namespace Trigonometry { /** ratio of circumference to diameter */ const Number PI = 3.14159; /** array of figures created */ Array figures; /** calculate the area of a circle */ Number calculateArea(Number radius) {} }
synopsis: //:NSBEGIN $token C++: namespace $token { java: public class $token {
synopsis: //:NSCONSTANT $line C++: const $line; java: public static final $line;
synopsis: //:NSVAR $line C++: $line; java: public static $line;
synopsis: //:NSFUNCTION $line C++: $line {} java: $line {}
synopsis: //:NSEND [$token] C++: } java: }
example javascript input (with no javadoc comments):
//:CLBEGIN Foo extends Bar function Foo() { Bar.call(this); } Foo.prototype = new Bar(); Foo.prototype.constructor = Foo; //:CLCONSTANT int CLASSICAL_PI = 3 Foo.CLASSICAL_PI = 3; //:CLEND Foo
example C++ output:
class Foo : public Bar {public: static const int CLASSICAL_PI = 3; };
synopsis: //:CLBEGIN $classname [extends $superclass] [implements $interface1, $interface2] C++: class $classname [: public $superclass, public $interface1, public $interface2] { public: java: public $classname [extends $superclass] [implements $interface1, $interface2] {
synopsis: //:CLCONSTANT $line C++: static const $line; java: public static final $line;
synopsis: //:CLIVAR $line C++: $line;
synopsis: //:CLCVAR $line C++: static $line;
synopsis: //:CLIMETHOD $line C++: $line {}
synopsis: //:CLCONSTRUCT $line C++: $line {}
synopsis: //:CLCMETHOD $line C++: static $line {}
synopsis: //:CLAMETHOD $line C++: virtual $line = 0; java: abstract $line;
synopsis: //:IFBEGIN $token C++: class $token { public: java: interface $token {
synopsis: //:IFCONSTANT $line C++: static const $line; java: static final $line;
synopsis: //:IFMETHOD $line C++: virtual $line = 0; java: $line;
synopsis: //:IFEND C++: }; java: }
synopsis: //:GLCONSTANT $line C++: const $line; java: public static final $line;
synopsis: //:GLVAR $line C++: $line; java: $line;
synopsis: //:GLFUNCTION $line C++: $line {}
synopsis: //:ENUMBEGIN $typename C++: enum $typename {
synopsis: //:ENUMVAL $valname $value $comment C++: $valname [= $value], /**< $comment */
synopsis: //:ENUMEND C++: };
The utility will attempt to load a module named 'src2doc_extend.pm' (from the perl include path, augmented by the directory this program is in). If available, it must define a global variable $CMD_HOOK which is a sub taking parameters ($lang, $cmd, $args). When called, it can read any number of input lines. It should return false if it does not handle the command.
Currently only C++ output is implemented.
The opposite side of this utility is src2code.pl, which extracts just the code, not the comments.
Purists will realize that these utilities do not actually constitute literate programming. Knuth's "weave" (get documentation) and "tangle" (get code) support re-ordering of code, and in general presumes a more intimate relationship between documentation and executable artifacts.
As part of his JsUnit project, Jorg Schaible implemented a perl program that converts javascript source code to C++ suitable for doxygen processing: js2doxy.pl, http://jsunit.berlios.de/internal.html .
It generates C++ not from parsed comments (as we do), but instead by attempting to parse the javascript source code itself. If you write your code following his conventions, that can be more convenient. However, it makes the tool javascript-specific, and limits the javascript idioms that can be used. The tool also limits the set of javadoc tags that can be used. It is also not set up to be used directly as a doxygen filter (src2doc.pl is). Instead it supplies a largely superfluous 'jsdoc' wrapper.
An apparently abandoned sourceforge project at http://jsdoc.sourceforge.net/ it consists of 1-page perl program that attempts to emulate javadoc.
Located at http://www.stud.tu-ilmenau.de/~thla-in/scripts/JSdoc/ and is unrelated to the sourceforge JSDoc project. It seems not to be released, just described.
There is a basic javascript program that like the perl jsdoc attempts to implement javadoc: http://lxr.mozilla.org/mozilla/source/js/rhino/examples/jsdoc.js
Copyright 2003, Mark D. Anderson, mda@discerning.com.
This is free software; you can redistribute it and/or modify it under the same terms as Perl itself.