Thread overview | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 23, 2005 Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
With all this talk about generating HTML files with boilerplate, I use a simple macro text preprocessor to do it. Here it is, and btw it shows what can be done with just a few lines of D! --------------------------------- // Copyright (C) 2005 by Digital Mars www.digitalmars.com // All Rights Reserved // Written by Walter Bright import std.file; import std.stdio; import std.c.stdlib; import std.string; import std.ctype; import std.date; void usage() { printf( "Macro process file.\n" "Use:\n" " macro infile outfile args...\n" " args are of the form name=value\n" " $(name) in text is replaced with value\n" ); } int main(char[][] cmdargs) { int i; char[] arg; char[][] args; char[] fin = null; char[] fout = null; int errors; writefln("macro 1.01"); if (cmdargs.length < 3) { usage(); return EXIT_FAILURE; } errors = 0; args.length = cmdargs.length - 3; args.length = 0; for (i = 1; i < cmdargs.length; i++) { arg = cmdargs[i]; if (i <= 2) { if (arg[0] == '-') { writefln("unrecognized switch '%s'", arg); errors++; } else if (i == 1) fin = arg; else fout = arg; } else args ~= arg; } if (errors) return EXIT_FAILURE; predefinedMacros(); foreach (char[] arg; args) macroInsert(arg); char[] input = cast(char[])std.file.read(fin); char[] output; output = process(input); std.file.write(fout, output); return EXIT_SUCCESS; } char[] [char[]] mactab; void macroInsert(char[] arg) { int i = find(arg, '='); if (i == -1) throw new Error("expected name=value, not " ~ arg); char[] name = strip(arg[0 .. i]); char[] value = stripl(arg[i + 1 .. length]); mactab[name] = value; } void predefinedMacros() { d_time t = getUTCtime(); char[] value = toDateString(t); mactab["__DATE__"] = value; value = format(cast(long)YearFromTime(t)); mactab["__YEAR__"] = value; } char[] process(char[] input) { char[][] lines; char[] output; lines = splitlines(input); // Do backsplash line splicing for (int i = 0; i + 1 < lines.length; ) { char[] line = lines[i]; if (line.length && line[length - 1] == '\\') { line.length = line.length - 1; // chop off backslash line ~= '\n'; line ~= lines[i + 1]; lines[i] = line; for (int j = i + 1; j + 1 < lines.length; j++) lines[j] = lines[j + 1]; lines.length = lines.length - 1; //writefln("line = '%s'", line); } else i++; } // Macro process lines char[] result; foreach (char[] line; lines) { result.length = 0; for (int i = 0; i < line.length; ) { int j; j = find(line[i .. length], '$'); if (j == -1) { result ~= line[i .. length]; break; } j += i; result ~= line[i .. j]; if (j + 1 == line.length) { result ~= '$'; break; } if (line[j + 1] == '$') { result ~= '$'; i = j + 2; continue; } if (isalpha(line[j + 1])) { result ~= mactab[ line[j + 1 .. j + 2] ]; i = j + 2; continue; } if (line[j + 1] == '(' && j + 2 != line.length) { int k = find(line[j + 2 .. length], ')'); if (k != -1) { k += j + 2; result ~= mactab[ line[j + 2 .. k] ]; i = k + 1; continue; } } result ~= '$'; i = j + 1; } if (result.length && result[0] == '.') { if (result.length >= 4 && result[1 .. 4] == "set") { macroInsert(result[4 .. length]); continue; } else if (result.length >= 8 && result[1 .. 8] == "include") { char[] filename = strip(result[8 .. length]); char[] input = cast(char[])std.file.read(filename); output ~= process(input); continue; } else throw new Error("unknown dot command: " ~ result); } else { output ~= result; output ~= '\n'; } } return output; } |
August 23, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Here's an example of how I use it, this is std_random.txt, the eventual html is at www.digitalmars.com/d/phobos/std_random.html The header, footer, and sidebar are all boilerplate from macros.inc. --------------------------------------------------------------------------- .set TITLE=Digital Mars - The D Programming Language - std.random .set WIKI=Phobos/StdRandom .include macros.inc $(HEADER) $(PHOBOS_S) <h1 align=center>std.random</h1> <dl><dl> <dt>void <b>rand_seed</b>(uint seed, uint index) <dd>The random number generator is seeded at program startup with a random value. This ensures that each program generates a different sequence of random numbers. To generate a repeatable sequence, use <b>rand_seed</b>() to start the sequence. <i>seed</i> and <i>index</i> start it, and each successive value increments <i>index</i>. This means that the <i>n</i>th random number of the sequence can be directly generated by passing <i>index + n</i> to <b>rand_seed</b>(). <p> <dt>uint <b>rand</b>() <dd>Get next random number in sequence. <p> </dl></dl> $(PHOBOS_E) $(FOOTER) |
August 23, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | In "no frames" conversation I already written about XML commenting. Let me do it again. Why not store the same information in the same place: the code file? http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcoriXMLDocumentation.asp Your example would look like: /// <summary> /// The random number generator is seeded at program startup with a random value. /// This ensures that each program generates a different sequence of random numbers. /// To generate a repeatable sequence, use <see cref="rand_seed()"/> to start the sequence. /// The parameters start it, and each successive value increments index. This means that the nth random number of the sequence can be directly generated by passing index + n to <see cref="rand_seed()"/>. /// </summary> /// <param name="seed">the random number seed</param> /// <param name="index">each successive value increments index</param> /// <returns>void<returns> void rand_seed(uint seed, uint index) { seed = s; index = i; } /// <summary> /// Get next random number in sequence. /// </summary> /// <returns>next random number<returns> uint rand() { ...code... } And simle tools should work with this information after, fully cross/hyperlinked. Also, you don't need to write return and parameter types, it's already in the code. Also, compiler should check if the doc (xml comment) is outdated. If you have a problem with this, as it's sooo Microsoft-ish, well... Do something similar/equivalent... (But why reinvent the wheel?) If you are disturbed with comment in code... well first, unittest also appears to be there, and second, code editor should collapse the comment blocks. (Also, I'd like to ask if unittests _have_ to be in the same file than the tested code?) Regards, ElfQT |
August 23, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to ElfQT | "ElfQT" <dethjunk@yahoo.com> wrote in message news:deg1tc$26sq$1@digitaldaemon.com... > If you have a problem with this, as it's sooo Microsoft-ish, well... Do something similar/equivalent... (But why reinvent the wheel?) While it's a good idea, I find it just aesthetically ugly in the program source code. > (Also, I'd like to ask if unittests _have_ to be in the same file than the > tested code?) Nope. |
August 23, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Walter wrote:
> "ElfQT" <dethjunk@yahoo.com> wrote in message
> news:deg1tc$26sq$1@digitaldaemon.com...
>
>>If you have a problem with this, as it's sooo Microsoft-ish, well...
>>Do something similar/equivalent... (But why reinvent the wheel?)
>
>
> While it's a good idea, I find it just aesthetically ugly in the program
> source code.
>
>
I agree, it's truly ugly.
How about something cleaner, like Javadoc?
|
August 23, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hasan Aljudy | "Hasan Aljudy" <hasan.aljudy@gmail.com> wrote in message news:deg8gq$2n93$1@digitaldaemon.com... > I agree, it's truly ugly. > How about something cleaner, like Javadoc? Better, but still ugly. I should probably design a proper one <g>, but I just haven't given it much thought. |
August 23, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Hi, Walter wrote: > "ElfQT" <dethjunk@yahoo.com> wrote in message > news:deg1tc$26sq$1@digitaldaemon.com... > >>If you have a problem with this, as it's sooo Microsoft-ish, well... >>Do something similar/equivalent... (But why reinvent the wheel?) > > > While it's a good idea, I find it just aesthetically ugly in the program > source code. I agree. It's ugly, _and_ verbose. XML + triple slashes + indenting is just not a good combination. I think general-user documentation should be kept separate from the actual code. Comments in the code should be there primarily to help the people that create/maintain the module, not general programmers. >>(Also, I'd like to ask if unittests _have_ to be in the same file than the >>tested code?) > > Nope. What about creating a default unittest file per module? A sort of code-behind variant so that all that test code can be by itself. For instance: Foo.d : Actual module code. Foo.ut.d : Unittest for Foo. I believe this would work because modules already can't contain periods. Also, if a .ut.d file doesn't exist, then it would be simply ignored. Cheers, --AJG. |
August 24, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to AJG | On Tue, 23 Aug 2005 19:51:02 -0400, AJG wrote: > Hi, > > Walter wrote: >> "ElfQT" <dethjunk@yahoo.com> wrote in message news:deg1tc$26sq$1@digitaldaemon.com... >> >>>If you have a problem with this, as it's sooo Microsoft-ish, well... Do something similar/equivalent... (But why reinvent the wheel?) >> >> While it's a good idea, I find it just aesthetically ugly in the program source code. > > I agree. It's ugly, _and_ verbose. XML + triple slashes + indenting is just not a good combination. ~~~~ Shudder ~~~~ > I think general-user documentation should be kept separate from the actual code. Comments in the code should be there primarily to help the people that create/maintain the module, not general programmers. I place documentation inside the source for my projects purely from a practical aspect. As I'm the one person doing both the coding and the documentation, it is more efficient for me to keep them together. Basically if they were in different files they would soon get out of synchronization. However, if I had the luxury of a separate person doing the docs, they would be separated. That's why I've developed a documentation mark up language and a tool to extract it years ago and still use it. The Build utility's HTML docs are generated from the mark up stuff embedded in the source code. -- Derek (skype: derek.j.parnell) Melbourne, Australia 24/08/2005 10:03:37 AM |
August 24, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to AJG | AJG wrote: > Hi, > > Walter wrote: > >> "ElfQT" <dethjunk@yahoo.com> wrote in message >> news:deg1tc$26sq$1@digitaldaemon.com... >> >>> If you have a problem with this, as it's sooo Microsoft-ish, well... >>> Do something similar/equivalent... (But why reinvent the wheel?) >> >> >> >> While it's a good idea, I find it just aesthetically ugly in the program >> source code. > > > I agree. It's ugly, _and_ verbose. XML + triple slashes + indenting is just not a good combination. I think that ideally, it would be Python-esque. IE, whitespace in docs would be syntactically significant. eg, a D-style comment might be /*D functionName Author: ABC Date:xyz Copyright:2005 param1 meaning of this parameter param2 it identifies a parameter by the whitespace at start of the line. If when finished parsing the comment, the list of parameters doesn't match the params in the comment, it's an error if #params in comment >0. (so explaining params is optional, but if you explain one, you must explain all, and mustn't explain any that aren't there). param3 this is another parameter One-line summary Long explanation, which travels over several lines. */ The idea being that if you begin a comment with the special D-comment identifier, you must format it in a particular good style. Some existing well-commented code should automatically be readable. I don't see why you need any kind of <param> tokens, human beings seem to be able to parse (well-formed) comments perfectly well without them. |
August 24, 2005 Re: Macro text preprocessor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Walter wrote: <snip> > <dt>uint <b>rand</b>() > <dd>Get next random number in sequence. > <p> > > </dl></dl> Oh. I'd begun to assume the misplaced <p> tags dotted about the pages were a bug in your preprocessor. Looks like I was wrong. Welcome to HTML. The <p> tag marks the beginning of a paragraph, not the end of one. And it certainly doesn't belong /between/ elements of a list. There's also </p>, which marks the end of a paragraph, but that's optional.... Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- a->--- UB@ P+ L E@ W++@ N+++ o K- w++@ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit. |
Copyright © 1999-2021 by the D Language Foundation