MathGroup Archive 1995

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Crossreference, code documentation

Hi all,

I wrote looking for a documentation and maintenance package.  

Here is a solution to two of my major problems (since I asked such long 
questions, maybe I'm adding insult to injury by providing long answers, 
rather than being helpful.  But I think code documentation and maintenance 
tools will be very helpful to a lot of people.  I post this also to save 
anyone who is inclined to spend the time to respond with solutions to my 
original messages -- I'm content that I've solved 3 of my 4 problems).

I haven't gotten any responses yet except one suggesting developing in C++ 
or Common Lisp instead, so I thought I'd go ahead and develop the three 
tools I needed immediately.

One of my needs is something that takes a source code .m file, 
and, given a table of "old variable name, new variable name" produces a new 
source code .m file with these variable name replacements.  I believe I've 
found a good answer to this problem.  The main secret is to 
create a list, called specCharsL, of all special characters, i.e. all 
characters that are non-alphanumeric and not $.  The significance of 
these special characters is that they cannot be part of a variable or 
function name.

Then I use the specCharsL as a TokenWords, when I ReadList my source code 
file into programAr:

  programAr = ReadList[filename,Word,rsn,TokenWords -> specCharsL];
                                      ^- recordSeparators -> {}
programAr is the source code from filename, but parsed into a list of 
elements.  Some elements of the list are alphanumeric strings (strings 
containing letters, digits, and $ only), and other elements being special 
characters only.  The alphanumeric strings are generally whole variable 
names or function names.  (They might also be regular words in comments, 
but that doesn't bother me).

The other major step, is that given a list of old variable name -> new 
variable name replacement rules, I then use ReplaceAll (the /. operator)
to replace all instances of old variable names with their corresponding 
new variable names:
  newProgramAr = programAr /. oldNewReplacementRuleL;  

The complete program is below (it works, but I'm still developing related 
tools, so things are still open and global):

 rsn = ( RecordSeparators -> {} )
 specialCharsGL = Map[FromCharacterCode, Join[ Range[0,35], Range[37,47],
                    Range[58,64], Range[91,96], Range[123,127] ] ];
 oldNewVarbsGL = { { "crL", "chromeL" }, {"grL", "grandTotL"}, 
                   {"ebPL", "ebGPL"},  { "nebPL", "nebXYZ" } };  

(*##### FAR f### findAndReplace #######*)    
findAndReplace[fname_,oldNewL_,specCharsL_] := Module[{},    
        (* programAr is a list whose elements consist of either
           names or special characters *)
  programAr = ReadList[fname,Word,rsn,TokenWords -> specCharsL];

        (* oldNewReplacementRuleL is the oldnewL matrix
           converted to a list of replacement rules *)
  oldNewReplacementRuleL = Map[ ( # /. {a_,b_} -> a -> b )&, oldNewL ];
  newProgramAr = programAr /. oldNewReplacementRuleL;  
  newProgramCodeStr = StringJoin @@ newProgramAr;
  Print["Result is in newProgramCodeStr.  Here are first 1000 characters:"];
  Print[]; Print[StringTake[newProgramCodeStr,1000]];
  ans = Input["Do you want to save to output file \"out\"?  (y/n):  "];
  If[ ToUpperCase[ToString[ans]] == "Y",
       WriteString["out", newProgramCodeStr]; Close["out"] ]; (* If *)
] (* end findAndReplace *)
I've also made sure that the above does not have a substring replacement 
problem.  That is, given replacement rules such as: 
  { "len" -> "strLength", "maxlen" -> "maxVectorLength" }
I don't have to worry about the "len" in "maxlen" being replaced by 
"strLength" to yield the horribly wrong maxstrLength.  With the way the 
file is parsed in programAr, and the way that the /. operator works, only 
complete strings are replaced by complete strings.

I believe that another need of mine, finding variable names that don't 
match an "approved" list of variable names, is easily obtained by using 
MemberQ, i.e. along the lines of

   For[i = 1, i<= Length[programAr], i++,
        If[ !MemberQ[programAr[[i]],approvedL], 
              AppendTo[unmatchedNameL, programAr] ] ]

It will be pretty inefficient, in that most of the elements in programAr 
are single special characters like "["  which needn't be checked against 
the approvedL.  (I use the suffix "L" to mean a list).  I might weed those 
out first.

I'd also probably run my "comment stripper" program on the file 
first before producing programAr and running the above program.  So as not 
to compare every lousy word in a comment against the approved list, and 
adding it to the unmatchedNameL in the usual case that there isn't a match.

The third tool I needed was the comment stripper program, which removes 
all comments from a .m file.  I have that working well.  But its so long, 
ugly, inelegant, and would take a lot of documentation to explain that I 
wouldn't think of posting it.  But anyone interested in complete working 
versions of these tools can email me -- though I might take a week or two 
to clean things up first.

The only major item remaining in my wish list is a program to build the 
function variable cross reference table:

 function      variable            global   global
 name          name       local?   used?    modified? 
 =========     ========   ======   =======  ==========
 func1         xabcF1      Y         N          N
 func1         xdefF1G     N         Y          N
 func2         x123F2      Y         N          N

This one looks tough.

Jim Larson

  • Prev by Date: Re: Crossreference, code documentation
  • Next by Date: MathLink documentation
  • Previous by thread: Re: Crossreference, code documentation
  • Next by thread: Re: Crossreference, code documentation