|
## Frank Lübeck
## Validating the manual and checking for text between
## chapters/sections/subsections.
##
LoadPackage( "GAPDoc" );
LoadPackage( "ctbllib" );
Read( "makedocreldata.g" );
if not IsBound( GAPInfo.ManualDataRef ) then
Error( "read the data from makedocrel.g first" );
fi;
pathtodoc:= GAPInfo.ManualDataRef.pathtodoc;;
main:= GAPInfo.ManualDataRef.main;;
bookname:= GAPInfo.ManualDataRef.bookname;;
pathtoroot:= GAPInfo.ManualDataRef.pathtoroot;;
files:= GAPInfo.ManualDataRef.files;;
# MakeGAPDocDoc( pathtodoc, main, files, bookname, pathtoroot );;
Print("Collecting document for ref manual . . .\n");
doc := ComposedDocument( "GAPDoc", pathtodoc, main, files, true );
gapdocdtd := Filename(DirectoriesPackageLibrary("gapdoc"), "../gapdoc.dtd");
Print("Loading gaprxp . . .");
if LoadPackage("gaprxp") = true then
Print(" ok\nParsing with rxp (with validation) . . .\n");
resrxp := XMLParseWithRxp(doc[1], [ "-V", "-D", "Book",
gapdocdtd]);
Print("ERRORS:\n");
for a in resrxp.err do
Print(a,"\n");
od;
Print("Creating parse tree . . .\n");
tree := XMLMakeTree(resrxp.out);
else
Print(" not found!\nParsing with GAPDoc parser (without validation) . . .");
tree := ParseTreeXMLString( doc[1], doc[2] );
Print("Calling CheckAndCleanGapDocTree . . .\n");
CheckAndCleanGapDocTree( tree );
fi;
AddParagraphNumbersGapDocTree(tree);
# Utility, substitutes content of chapters, section, subsections respectively
# by strings like ___Chapter[4,0,0,0].
FoldSectioning := function(tree, sectype)
local fun, elnams;
if sectype = "Chapter" then
elnams := ["Chapter","TitlePage","Appendix","Bibliography"];
elif sectype = "Section" then
elnams := ["Section"];
elif sectype = "Subsection" then
elnams := ["Subsection", "ManSection"];
else
elnams := [sectype];
fi;
fun := function(r)
if r.name in ["XMLPI", "XMLDOCTYPE", "XMLCOMMENT", "COMMENT"] then
if not IsBound(r.origcontent) then
r.origcontent := r.content;
fi;
r.content := "";
elif r.name in elnams then
if not IsBound(r.origcontent) then
r.origcontent := r.content;
fi;
r.content := Concatenation("___", r.name,
SubstitutionSublist(String(r.count), " ",""), "\n");
fi;
end;
ApplyToNodesParseTree(tree, fun);
end;
# remove the folding
MoveBackOrigContent := function(tree)
ApplyToNodesParseTree(tree, function(r) if IsBound(r.origcontent) then
r.content := r.origcontent; Unbind(r.origcontent); fi;end);
end;
# Show the structure of a folded (sub)tree. Text between sections is
# truncated after 3/4 of a line. Warnings are printed if there is text
# between sections. (Text before any section is fine.)
StringStructure := function(tree)
local str, sp, new, pos, r, i, iss;
str := GetTextXMLTree(tree);
NormalizeWhitespace(str);
str := SubstitutionSublist(str, " ___", "\n___");
sp := SplitString(str,"","\n");
new := [];
for r in sp do
if Length(r) > 2 and r{[1..3]} = "___" then
pos := Position(r,']');
if pos = Length(r) then
Add(new, r);
else
Add(new, r{[1..pos]});
Add(new, r{[pos+1 .. Minimum(pos+60, Length(r))]});
fi;
else
Add(new, r{[1..Minimum(60, Length(r))]});
fi;
od;
# print warnings
iss := new[1]{[1..Minimum(Length(new[1]),3)]} = "___";
for i in [2..Length(new)] do
if new[i]{[1..Minimum(Length(new[i]),3)]} = "___" then
iss := true;
else
if iss then
Print("Warning: text after ",new[i-1],"\n",new[i]," . . .\n");
fi;
iss := false;
fi;
od;
return JoinStringsWithSeparator(new, "\n");
end;
# And an example how to use above utilities:
SectionStructuresWithWarnings := function(tree)
local chstr, chaps, chapstr, secs, secstr, ch, s;
MoveBackOrigContent(tree);
Print("###### Checking chapter structure . . .\n");
FoldSectioning(tree, "Chapter");
chstr := StringStructure(tree);
MoveBackOrigContent(tree);
Print("###### Checking section structures of chapters . . .\n");
chaps := XMLElements(tree,["Chapter","Appendix"]);
chapstr := [];
for ch in chaps do
Print("Chapter ", ch.count, "\n");
FoldSectioning(ch,"Section");
Add(chapstr, StringStructure(ch));
od;
MoveBackOrigContent(tree);
Print("###### Checking subsection structures of sections . . .\n");
secs := XMLElements(tree,["Section"]);
secstr := [];
for s in secs do
#Print("Section ", s.count, "\n");
FoldSectioning(s,"Subsection");
Add(secstr, StringStructure(s));
od;
MoveBackOrigContent(tree);
return [chstr, chapstr, secstr];
end;
# a variant of 'WordsString'
Words := function(str)
local res;
res := SplitString(str, "", " \n\t\r\240\302\"\\:;,.'/?[]{}\|=+-_()<>*&^%$#@!~`");
return res;
end;
# a fragment of what one could do with a word list, would like to find
# a list of words for the spell checker
CheckWords := function(wlist)
local bnd, fu, gapv;
# numbers
wlist := Filtered(wlist, a-> not ForAll(a, IsDigitChar));
# documented GAP variables
wlist := Filtered(wlist, a-> not IsDocumentedWord(a));
# further bound GAP variables
bnd := Filtered(wlist, a-> IsBoundGlobal(a));
wlist := Filtered(wlist, a-> not IsBoundGlobal(a));
# further words which may refer to GAP variables
fu := function(s)
s := Filtered(s, x-> IsDigitChar(x) or IsUpperAlphaChar(x));
return Length(s) > 1;
end;
gapv := Filtered(wlist, fu);
wlist := Filtered(wlist, a-> not fu(a));
return [wlist, gapv, bnd];
end;
# a general utility, could maybe made more general to cover FoldSectioning
# as well
HideElementsXMLTree := function(tree, elts)
local fu;
if IsString(elts) then
elts := [elts];
fi;
fu := function(r)
if r.name in elts then
if not IsBound(r.origcontent) then
r.origcontent := r.content;
fi;
r.content := "";
fi;
end;
ApplyToNodesParseTree(tree, fu);
end;
# remove the folding or hiding
MoveBackOrigContent := function(tree)
ApplyToNodesParseTree(tree, function(r) if IsBound(r.origcontent) then
r.content := r.origcontent; Unbind(r.origcontent); fi;end);
end;
# as the name says
SomeTests := function(tree)
local txt, wds, chk;
# after hiding these there shouldn't be any GAP variable names any more
HideElementsXMLTree(tree, ["C","M","Math","Display","A","Arg", "Example",
"XMLPI", "XMLDOCTYPE", "XMLCOMMENT", "COMMENT"]);
txt := GetTextXMLTree(tree);
txt := SubstitutionSublist(txt, "\342\200\223", "-");
wds := Set(Words(txt));
chk := CheckWords(wds);
return chk;
end;
# f is called before recursion, g afterwards
# Will generalize ApplyToNodesParseTree to a 3-arg version . . .
ApplyToNodes2 := function ( r, f, g )
local ff;
ff := function ( rr )
local a;
if IsList( rr.content ) and not IsString( rr.content ) then
for a in rr.content do
f( a );
ff( a );
g( a );
od;
fi;
return;
end;
f( r );
ff( r );
g( r );
return;
end;
# This finds <A> elements in outside ManSections (should not happen) and
# strings in <A> elements which are not given in Arg attributes of the
# current ManSection.
CheckAContent := function(tree)
local c1, c2, fu, g;
c1 := 0;
c2 := 0;
fu := function(r)
local w;
if r.name = "ManSection" then
GAPInfo.ARGLIST := [];
elif r.name in ["Func","Oper","Meth","Filt","Prop",
"Attr","Var","Fam","InfoClass"] then
if IsBound(r.attributes.Arg) then
Append(GAPInfo.ARGLIST, WordsString(r.attributes.Arg));
fi;
elif r.name in ["A", "Arg"] then
if not IsBound(GAPInfo.ARGLIST) then
Print("<A> outside ManSection: ", GetTextXMLTree(r),"\n");
c1 := c1+1;
else
w := WordsString(GetTextXMLTree(r));
w := Filtered(w, a-> not a in GAPInfo.ARGLIST);
if Length(w) > 0 then
Print("Wrong <A>: ",w,"/",GAPInfo.ARGLIST,"\n");
c2 := c2+1;
fi;
fi;
fi;
end;
g := function(r)
if r.name = "ManSection" then
Unbind(GAPInfo.ARGLIST);
fi;
end;
ApplyToNodes2(tree, fu, g);
Print(c1," outside ManSection, ",c2," wrong usages.\n");
end;
# one call that shows text between subsections
strs := SectionStructuresWithWarnings(tree);
[ Dauer der Verarbeitung: 0.29 Sekunden
(vorverarbeitet)
]
|