# - - - B o d y . _ _ i n i t _ _ - - - #### Case 1: fileName does not name a readable, valid body file #-- 1 -- self.topic = topic self.seeList = [] self.etemplate = topic.defaultTemplate self.topic: topic self.seeList: [] self.etemplate: topic.defaultTemplate #-- 2 -- # [ self.enext := a Target object representing self.topic's # right-hand sibling in topic.plan, if any, # else None # self.eprev := a Target object representing self.topic's # left-hand sibling in topic.plan, if any, # else None # self.seeList := self.seeList + (a Target object # representing self.topic's parent, if any) ] self.topic: topic self.seeList: [(a Target representing self.topic's parent, if any)] self.etemplate: topic.defaultTemplate self.enext: Target representing self.topic's RH sibling in topic.plan, if any, else None self.eprev: Target representing self.topic's LH sibling in topic.plan, if any, else None #-- 3 -- # [ if fileName names a readable, valid body file -> ... # else -> # Log() +:= error message(s) # self.topic.plan := self.topic.plan with link variants # added from that file, if any # raise IOError ] self.topic: topic self.seeList: [(a Target representing self.topic's parent, if any)] self.etemplate: topic.defaultTemplate self.enext: Target representing self.topic's RH sibling in topic.plan, if any, else None self.eprev: Target representing self.topic's LH sibling in topic.plan, if any, else None self.topic.plan: @ with link variants added from fileName, if any Log(): @+(error message) raise IOError #-- TARGET -- OK [ if (topic is a Topic object) and (fileName is a string) -> if fileName names a readable, valid body file -> ... else -> Log() +:= error message(s) raise IOError ] # - - - B o d y . _ _ i n i t _ _ - - - #### Case 2: fileName names a readable, valid body file #-- 1 -- self.topic = topic self.seeList = [] self.etemplate = topic.defaultTemplate self.topic: topic self.seeList: [] self.etemplate: topic.defaultTemplate #-- 2 -- # [ self.enext := a Target object representing self.topic's # right-hand sibling in topic.plan, if any, # else None # self.eprev := a Target object representing self.topic's # left-hand sibling in topic.plan, if any, # else None # self.seeList := self.seeList + (a Target object # representing self.topic's parent, if any) ] self.topic: topic self.seeList: [(a Target representing self.topic's parent, if any)] self.etemplate: topic.defaultTemplate self.enext: Target representing self.topic's RH sibling in topic.plan, if any, else None self.eprev: Target representing self.topic's LH sibling in topic.plan, if any, else None #-- 3 -- # [ if fileName names a readable, valid body file -> # self := self modified to reflect the contents # of that file # self.topic.plan := self.topic.plan with link variants # added from that file # else -> ... ] self.topic: topic self.seeList: [(a Target representing self.topic's parent, if any)] self.etemplate: topic.defaultTemplate self.enext: Target representing self.topic's RH sibling in topic.plan, if any, else None self.eprev: Target representing self.topic's LH sibling in topic.plan, if any, else None self: @, modified to reflect the contents of fileName self.topic.plan: @ with link variants added from fileName #-- TARGET -- OK [ if (topic is a Topic object) and (fileName is a string) -> if fileName names a readable, valid body file -> return a new Body object representing that fileName as that topic else -> ... ] (invariants) .topic: As passed to constructor .author: [ if self contains an tag -> the content of that tag as a string else -> None ] .seeList: [ effective-see-list(self, self.topic.plan) ] .enext: [ effective-next(self, self.topic.plan) ] .eprev: [ effective-prev(self, self.topic.plan) ] .etemplate: [ effective-template(self, self.topic.plan) ] .text: [ if self is valid -> self's expanded body text as a list of strings else -> None ] .updated: [ if self contains an tag -> the value of the DATE attribute as a string else -> None ] # - - - B o d y . _ _ f i n d S i b l i n g s - - - #### Case 1: self is the root #-- 1 -- self.enext = None self.eprev = None self.enext: None self.eprev: None #-- 2 -- # [ if self.topic has no parent -> # return # else -> ... ] self.enext: None self.eprev: None return #-- TARGET -- [ self.enext := a Target object representing self.topic's right-hand sibling in topic.plan, if any, else None self.eprev := a Target object representing self.topic's left-hand sibling in topic.plan, if any, else None self.seeList := self.seeList + (a Target object representing self.topic's parent, if any) ] # - - - B o d y . _ _ f i n d S i b l i n g s - - - #### Case 2: self is not the root #-- 1 -- self.enext = None self.eprev = None self.enext: None self.eprev: None #-- 2 -- # [ if self.topic has no parent -> ... # else -> # parent := parent of self.topic # self.seeList +:= a Target representing parent of self.topic ] self.enext: None self.eprev: None self.seeList: @+(a Target representing self.topic's parent) #-- 3 -- # [ if self.topic has no left sibling -> I # else -> # self.eprev := a Target object for self.topic's left sibling ] self.enext: None self.eprev: if self.topic has a left sibling, a Target object for that sibling, else None self.seeList: @+(a Target representing self.topic's parent) #-- 4 -- # [ if self.topic has no right sibling -> I # else -> # self.enext := a Target object for self.topic's right sibling ] self.enext: if self.topic has a right sibling, a Target object for that sibling, else None self.eprev: if self.topic has a left sibling, a Target object for that sibling, else None self.seeList: @+(a Target representing self.topic's parent) #-- TARGET -- OK [ self.enext := a Target object representing self.topic's right-hand sibling in topic.plan, if any, else None self.eprev := a Target object representing self.topic's left-hand sibling in topic.plan, if any, else None self.seeList := self.seeList + (a Target object representing self.topic's parent, if any) ] # - - - B o d y . _ _ r e a d - - - #### Case 1: fileName does not name a readable file #-- 1 -- # [ errCount := err count from Log() # self.text := "" ] errCount: @(Log().count()) self.text: "" #-- 2 -- # [ if fileName names a readable file -> ... # else -> # Log() +:= error message # raise IOError ] errCount: @(Log().count()) self.text: "" Log(): @+(error message) raise IOError #-- TARGET -- OK [ if fileName names a readable, valid body file -> ... else -> Log() +:= error message(s) self.topic.plan := self.topic.plan with link variants added from that file, if any raise IOError ] # - - - B o d y . _ _ r e a d - - - #### Case 2: fileName is readable but not valid #-- 1 -- # [ errCount := err count from Log() # self.text := "" ] errCount: @(Log().count()) self.text: "" #-- 2 -- # [ if fileName names a readable file -> # scan := a new Scan object positioned at the start of # that file # else -> ... ] errCount: @(Log().count()) self.text: "" scan: a Scan object positioned at the start of fileName #-- 3 -- # [ if scan contains a valid body file -> ... # else -> # Log() +:= error message(s) # self := self modified to reflect valid parts # of the file, if any # self.topic.plan := self.topic.plan with valid link variants # added from that file, if any ] errCount: @(Log().count()) self.text: "" scan: a Scan object positioned at the start of fileName Log(): @+(error message(s)) self: @, modified to reflect valid parts of fileName, if any self.topic.plan: @ with valid link variants added from fileName, if any #-- 4 -- # [ if errCount < (count of errors from Log()) -> # raise IOError # else -> ... ] errCount: @(Log().count()) self.text: "" scan: a Scan object positioned at the start of fileName Log(): @+(error message(s)) self: @, modified to reflect valid parts of fileName, if any self.topic.plan: @ with valid link variants added from fileName, if any raise IOError #-- TARGET -- OK [ if fileName names a readable, valid body file -> ... else -> Log() +:= error message(s) self.topic.plan := self.topic.plan with link variants added from that file, if any raise IOError ] # - - - B o d y . _ _ r e a d - - - #### Case 3: fileName is readable and valid #-- 1 -- # [ errCount := err count from Log() # self.text := "" ] errCount: @(Log().count()) self.text: "" #-- 2 -- # [ if fileName names a readable file -> # scan := a new Scan object positioned at the start of # that file # else -> ... ] errCount: @(Log().count()) self.text: "" scan: a Scan object positioned at the start of fileName #-- 3 -- # [ if scan contains a valid body file -> # self := self modified to reflect the contents of # that file # self.topic.plan := self.topic.plan with link variants added # from that file # else -> ... ] errCount: @(Log().count()) self.text: "" scan: a Scan object positioned at the start of fileName self: @, modified to reflect the contents of fileName self.topic.plan: @ with link variants added from fileName # - - - B o d y . _ _ r e a d T o k e n - - - #### Case 1: scan starts with a badly-formed tag #-- 1 -- # [ if scan starts with "<" but that begins no valid SGML tag -> # scan := scan advanced after the next ">" or to EOF, # whichever comes first # Log() +:= error message(s) # else if input is a "<" starting a syntactically valid tag -> ... # else -> ... ] scan: @, advanced past the "<" and after the next ">" or EOF, whichever comes first Log(): @+(error message(s)) #-- TARGET -- OK [ if scan starts with a badly formed tag -> scan := scan advanced past the tag or to EOF if it is unclosed, at least one character Log() +:= error message(s) else ... ] # - - - B o d y . _ _ r e a d T o k e n - - - #### Case 2: scan starts with a valid tag that is one of our ours #-- 1 -- # [ if scan starts with "<" but that begins no valid SGML tag -> ... # else if input is a "<" starting a syntactically valid tag # that is one of ours -> # scan := scan advanced past the tag, and past its closing # tag if paired # self := self modified to reflect that tag # self.topic.plan := self.topic.plan with link variants added # from the tag, if any # Log() +:= error messages from expansion, if any # else -> ... ] scan: @, advanced past the tag, and past its closing tag if paired self: @, modified to reflect the tag self.topic.plan: @ + (link variants from the tag, if any) Log(): @+(error messages from expansion, if any) #-- TARGET -- OK [ if scan starts with a badly formed tag -> ... else if scan starts with one of our tags -> scan := scan advanced past that tag, and past its closing tag if paired self := self modified to reflect that tag Log() +:= error messages from expansion, if any self.topic.plan := self.topic.plan with link variants added from scan, if any else ... ] # - - - B o d y . _ _ r e a d T o k e n - - - #### Case 3: scan starts with a valid tag that is NOT one of our ours #-- 1 -- # [ if scan starts with "<" but that begins no valid SGML tag -> ... # else if input is a "<" starting a syntactically valid tag # that is one of ours -> ... # else if input starts with a valid tag that is not ours -> # scan := scan advanced past the tag # self.text +:= the equivalent of that tag # else -> ... ] scan: @, advanced past the tag self.text: @+(the equivalent of that tag) #-- TARGET -- OK [ if scan starts with a badly formed tag -> ... else if scan starts with one of our tags -> ... else if scan starts with a valid tag -> scan := scan advanced past that tag self.text := self.text + (the equivalent of that tag) else -> ... ] # - - - B o d y . _ _ r e a d T o k e n - - - #### Case 4: scan does not start with a tag #-- 1 -- # [ if scan starts with "<" but that begins no valid SGML tag -> ... # else if input is a "<" starting a syntactically valid tag # that is one of ours -> ... # else if input starts with a valid tag that is not ours -> ... # else -> # scan := scan advanced to the next "<" or to EOF, whichever # comes first # self.text +:= characters from scan up to the next "<" or # EOF, whichever comes first ] scan: @, advanced to the next "<" or EOF self.text: @+(characters from scan up to next "<" or EOF) #-- TARGET -- OK [ if scan starts with a badly formed tag -> ... else if scan starts with one of our tags -> ... else if scan starts with a valid tag -> ... else -> scan := scan advanced up to the next tag, or EOF, whichever comes first self.text := self.text + (characters from scan up to the next tag, or EOF, whichever comes first) ] # - - - B o d y . _ _ r e a d N o n T a g - - - #### Case 1: There is a "<" on the line in scan #### Termination: returns out of loop #### False case: can't happen #### True case #-- 1 loop -- # [ if there is a "<" on this line -> # scan := scan advanced up to the "<" # self.text +:= text from scan up to the "<" # return # else ... ] scan: @, advanced up to the first "<" on the current line self.text: @+(text from scan up to first "<") #-- TARGET -- OK [ scan := scan advanced to the next "<" or to EOF, whichever comes first self.text +:= characters from scan up to the next "<" or EOF, whichever comes first ] # - - - B o d y . _ _ r e a d N o n T a g - - - #### Case 2: Scan contains no "<" and is last line #### Termination: advances to EOF, terminates loop #### False case: at EOF, terminates loop #### True case: #-- 1 loop -- # [ if there is a "<" on this line -> ... # else if this is the last line in scan -> # scan := scan advanced to EOF # self.text +:= remainder of line in scan + "\n" # else -> ... ] scan: @, advanced to EOF self.text: @+(remainder of line in scan)+"\n" #-- TARGET -- OK [ scan := scan advanced to the next "<" or to EOF, whichever comes first self.text +:= characters from scan up to the next "<" or EOF, whichever comes first ] # - - - B o d y . _ _ r e a d N o n T a g - - - #### Case 3: Scan contains no "<" and is not last line #-- 1 loop -- # [ if there is a "<" on this line -> ... # else if this is the last line in scan -> ... # else -> # scan := scan advanced to the next line # self.text +:= remainder of line in scan + "\n" ] scan: @, advanced to next line self.text: @+(text remaining from line in scan)+"\n" [ scan := scan advanced to the next "<" or to EOF, whichever comes first self.text +:= characters from scan up to the next "<" or EOF, whichever comes first ] scan: @, advanced to next line, then to next "<" or EOF self.text: @+(text remaining from line in scan)+"\n"+(text up to next "<" or EOF) #-- TARGET -- OK [ scan := scan advanced to the next "<" or to EOF, whichever comes first self.text +:= characters from scan up to the next "<" or EOF, whichever comes first ] # - - - B o d y . _ _ r e a d T a g - - - #### Case 1: scan starts with "<" not followed by a well-formed SGML tag #-- 1 -- # [ if scan starts with a syntactically valid HTML tag -> ... # else -> # scan := scan advanced after the next ">" or to EOF, # whichever comes first # Log() +:= error message(s) # return ] scan: @, advanced after next ">" or to EOF Log(): @+(error message(s)) #-- TARGET -- OK [ if scan starts with "<" but that begins no valid SGML tag -> scan := scan advanced after the next ">" or to EOF, whichever comes first Log() +:= error message(s) else ... ] # - - - B o d y . _ _ r e a d T a g - - - #### Case 2: scan starts with "<" followed by one of our tags which is #### not valid #-- 1 -- # [ if scan starts with a syntactically valid HTML tag -> # scan := scan advanced past the tag # tag := an SGMLTag object representing that tag with # the tag and attribute names lowercased # else -> # scan := scan advanced after the next ">" or to EOF, # whichever comes first # Log() +:= error message(s) # return ] scan: @, advanced past the opening tag tag: an SGMLTag object representing the opening tag #-- 2 -- # [ if webtag is not one of ours -> ... # else if webtag is ours but invalid -> # scan := scan advanced (if paired) past the closing tag # if any, or to EOF # Log() +:= error message(s) # else ... ] scan: @, advanced past the opening tag tag: an SGMLTag object representing the opening tag Log(): @+(error message(s)) #-- TARGET -- [ if scan starts with "<" but that begins no valid SGML tag -> ... else if input is a "<" starting a valid tag that is one of ours -> scan := scan advanced past the tag, and past its closing tag if paired self := self modified to reflect that tag and its content if paired Log() +:= error messages about semantics, if any else ... ] # - - - B o d y . _ _ r e a d T a g - - - #### Case 3: scan starts with "<" followed by one of our tags which is #### valid but paired with no closing tag #-- 1 -- # [ if scan starts with a syntactically valid HTML tag -> # scan := scan advanced past the tag # tag := an SGMLTag object representing that tag with # the tag and attribute names lowercased # else -> ... ] scan: @, advanced past the opening tag tag: an SGMLTag representing the opening tag #-- 2 -- # [ if webtag is not one of ours -> ... # else if webtag is ours but invalid -> # scan := scan advanced (if paired) past the closing tag # if any, or to EOF # Log() +:= error message(s) # else if webtag is valid and, if it is a paired tag, # scan contains a closing tag -> ... ] scan: @, advanced to EOF tag: an SGMLTag representing the opening tag Log(): @+(error message(s)) #-- TARGET -- OK [ if scan starts with "<" but that begins no valid SGML tag -> ... else if input is a "<" starting a valid tag that is one of ours -> scan := scan advanced past the tag, and past its closing tag if paired self := self modified to reflect that tag and its content if paired Log() +:= error messages about semantics, if any else ... ] # - - - B o d y . _ _ r e a d T a g - - - #### Case 4: scan starts with a valid tag unpaired tag of ours #-- 1 -- # [ if scan starts with a syntactically valid HTML tag -> # scan := scan advanced past the tag # tag := an SGMLTag object representing that tag with # the tag and attribute names lowercased # else -> ... ] scan: @, advanced past the tag tag: an SGMLTag object representing the tag #-- 2 -- # [ if webtag is not one of ours -> ... # else if webtag is ours but invalid -> ... # else if webtag is valid and, if it is a paired tag, # scan contains a closing tag -> # scan := scan advanced past the closing tag, if any, else # unchanged # self.text +:= expansion of the tag # self.topic.plan +:= link variant from the tag, if any # self := self modified to reflect any header information # in the tag ] scan: @, advanced past the tag tag: an SGMLTag object representing the tag self.text: @+(expansion of the tag) self.topic.plan: @+(link variant from the tag, if any) self: @, modified to reflect any header information in the tag #-- TARGET -- OK [ if scan starts with "<" but that begins no valid SGML tag -> ... else if input is a "<" starting a valid tag that is one of ours -> scan := scan advanced past the tag, and past its closing tag if paired self := self modified to reflect that tag and its content if paired Log() +:= error messages about semantics, if any else ... ] # - - - B o d y . _ _ r e a d T a g - - - #### Case 5: scan starts with a valid tag that is not one of ours #-- 1 -- # [ if scan starts with a syntactically valid HTML tag -> # scan := scan advanced past the tag # tag := an SGMLTag object representing that tag with # the tag and attribute names lowercased # else -> # scan := scan advanced after the next ">" or to EOF, # whichever comes first # Log() +:= error message(s) # return ] scan: @, advanced past the tag tag: an SGMLTag representing the tag #-- 2 -- # [ if webtag is not one of ours -> # self.text +:= source equivalent of tag # else ... ] scan: @, advanced past the tag tag: an SGMLTag representing the tag self.text: @+(source equivalent of tag) #-- TARGET -- OK [ if scan starts with "<" but that begins no valid SGML tag -> ... else if input is a "<" starting a valid tag that is one of ours -> ... else if scan starts with a valid tag -> scan := scan advanced past that tag self.text := self.text + (the equivalent of that tag) ] # - - - B o d y . _ _ d i s p a t c h T a g - - - #### Case 1: the tag is not one of ours #-- 1 -- lowGI = string.lower(tag.gi) lowGI: tag.gi, lowercased #-- 2 -- # [ if self.tagDispatchMap has a key for lowGI -> ... # else -> # self.text +:= source equivalent of tag # return ] self.text: @+(source equivalent of tag) return #-- TARGET -- OK [ if (tag is an SGMLTag object) and (self.tagDispatchMap is a dictionary mapping each of our lowercased tag names |-> the dispatch-routine for that tag) -> if webtag is not one of ours -> self.text +:= source equivalent of tag else ... ] # - - - B o d y . _ _ d i s p a t c h T a g - - - #### Case 2: the tag is ours but a closing tag other than #-- 1 -- lowGI = string.lower(tag.gi) lowGI: tag.gi, lowercased #-- 2 -- # [ if self.tagDispatchMap has a key for lowGI -> # dispatch := corresponding value from self.tagDispatchMap # else -> ... ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag #-- 3 -- # [ if tag is a closing tag and lowGI is not "head" -> # Log() +:= error message # return # else -> I ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag Log(): @+(error message) return #-- TARGET -- OK [ if (tag is an SGMLTag object) and (self.tagDispatchMap is a dictionary mapping each of our lowercased tag names |-> the dispatch-routine for that tag) -> if webtag is not one of ours -> ... else if webtag is ours but invalid -> scan := scan advanced (if paired) past the closing tag if any, or to EOF Log() +:= error message(s) else ... ] # - - - B o d y . _ _ d i s p a t c h T a g - - - #### Case 3: the tag is ours and unpaired and invalid #-- 1 -- lowGI = string.lower(tag.gi) lowGI: tag.gi, lowercased #-- 2 -- # [ if self.tagDispatchMap has a key for lowGI -> # dispatch := corresponding value from self.tagDispatchMap # else -> ... ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag #-- 3 -- # [ if tag is a closing tag and lowGI is not "head" -> ... # else -> I ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag #-- 4 -- # [ if dispatch(scan, tag) finds tag invalid -> # scan := scan advanced past the content and closing tag, # if expected and present, else to EOF # Log() +:= error(s) # if dispatch(scan, tag) finds tag valid -> ... ] scan: @ Log(): @+(error message(s)) #-- TARGET -- OK [ if (tag is an SGMLTag object) and (self.tagDispatchMap is a dictionary mapping each of our lowercased tag names |-> the dispatch-routine for that tag) -> if webtag is not one of ours -> ... else if webtag is ours but invalid -> scan := scan advanced (if paired) past the closing tag if any, or to EOF Log() +:= error message(s) else if webtag is valid and, if it is a paired tag, scan contains a closing tag -> ... ] # - - - B o d y . _ _ d i s p a t c h T a g - - - #### Case 4: the tag is ours and unpaired and valid #-- 1 -- lowGI = string.lower(tag.gi) lowGI: tag.gi, lowercased #-- 2 -- # [ if self.tagDispatchMap has a key for lowGI -> # dispatch := corresponding value from self.tagDispatchMap # else -> ... ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag #-- 3 -- # [ if tag is a closing tag and lowGI is not "head" -> ... # else -> I ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag #-- 4 -- # [ if dispatch(scan, tag) finds tag invalid -> ... # if dispatch(scan, tag) finds tag valid -> # scan := scan advanced past the content and closing tag, # if any, else unchanged # self.text +:= expansion of tag, if any # self.topic.plan +:= link variant from tag and content, if any # self := self modified to reflect any header information # from the tag and content ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag scan: @ self.text: expansion of tag, if any self.topic.plan: @ self: @, modified to reflect any header information from the tag and content #-- TARGET -- OK [ if (tag is an SGMLTag object) and (self.tagDispatchMap is a dictionary mapping each of our lowercased tag names |-> the dispatch-routine for that tag) -> if webtag is not one of ours -> ... else if webtag is ours but invalid -> ... else if webtag is valid and, if it is a paired tag, scan contains a closing tag -> scan := scan advanced past the closing tag, if any, else unchanged self.text +:= expansion of the tag self.topic.plan +:= link variant from the tag, if any self := self modified to reflect any header information in the tag ] # - - - B o d y . _ _ d i s p a t c h T a g - - - #### Case 5: the tag is ours, paired, and invalid #-- 1 -- lowGI = string.lower(tag.gi) lowGI: tag.gi, lowercased #-- 2 -- # [ if self.tagDispatchMap has a key for lowGI -> # dispatch := corresponding value from self.tagDispatchMap # else -> # self.text +:= source equivalent of tag # return ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag.gi, lowercased #-- 3 -- # [ if tag is a closing tag and lowGI is not "head" -> # Log() +:= error message # return # else -> I ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag.gi, lowercased #-- 4 -- # [ if dispatch(scan, tag) finds tag invalid -> # scan := scan advanced past the content and closing tag, # if expected and present, else to EOF # Log() +:= error(s) # if dispatch(scan, tag) finds tag valid -> ... ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag.gi, lowercased scan: scan advanced past the content and closing tag, if present, else EOF Log(): @+(error message(s)) #-- TARGET -- [ if (tag is an SGMLTag object) and (self.tagDispatchMap is a dictionary mapping each of our lowercased tag names |-> the dispatch-routine for that tag) -> if webtag is not one of ours -> ... else if webtag is ours but invalid -> scan := scan advanced (if paired) past the closing tag if any, or to EOF Log() +:= error message(s) else ... ] # - - - B o d y . _ _ d i s p a t c h T a g - - - #### Case 6: the tag is ours, paired, and valid #-- 1 -- lowGI = string.lower(tag.gi) lowGI: tag.gi, lowercased #-- 2 -- # [ if self.tagDispatchMap has a key for lowGI -> # dispatch := corresponding value from self.tagDispatchMap # else -> # self.text +:= source equivalent of tag # return ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag.gi, lowercased #-- 3 -- # [ if tag is a closing tag and lowGI is not "head" -> # Log() +:= error message # return # else -> I ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag.gi, lowercased #-- 4 -- # [ if dispatch(scan, tag) finds tag invalid -> ... # if dispatch(scan, tag) finds tag valid -> # scan := scan advanced past the content and closing tag, # if any, else unchanged # self.text +:= expansion of tag, if any # self.topic.plan +:= link variant from tag and content, if any # self := self modified to reflect any header information # from the tag and content ] lowGI: tag.gi, lowercased dispatch: dispatch-routine for tag.gi, lowercased scan: @, advanced past the content and closing tag self.text: @+(expansion of tag, if any) self.topic.plan: @+(link variant from tag and content, if any) self: @, modified to reflect tag and content #-- TARGET -- OK [ if (tag is an SGMLTag object) and (self.tagDispatchMap is a dictionary mapping each of our lowercased tag names |-> the dispatch-routine for that tag) -> if webtag is not one of ours -> ... else if webtag is ours but invalid -> ... else if webtag is valid and, if it is a paired tag, scan contains a closing tag -> scan := scan advanced past the closing tag, if any, else unchanged self.text +:= expansion of the tag self.topic.plan +:= link variant from the tag, if any self := self modified to reflect any header information in the tag ] # - - - B o d y . _ _ p a r s e A u t h o r T a g - - - #### Case 1: scan does not contain an tag #-- 1 -- # [ if scan contains a valid tag before EOF -> ... # else -> # scan := scan advanced to EOF # content := None # Log() +:= error message ] scan: @, advanced to EOF content: None Log(): @+(error message) #-- 2 -- # [ if content is None -> I # else if tag has any attributes -> # Log() +:= error message # else -> # self.author := content ] scan: @, advanced to EOF content: None Log(): @+(error message) #-- TARGET -- OK [ if scan contains a valid tag somewhere before EOF -> ... else -> scan := scan advanced to EOF Log() +:= error message ] # - - - B o d y . _ _ p a r s e A u t h o r T a g - - - #### Case 2: scan contains an invalid tag #-- 1 -- # [ if scan contains a valid tag before EOF -> # scan := scan advanced past that tag # content := text from scan up to tag # else -> ... ] # scan := scan advanced to EOF # content := None # Log() +:= error message ] scan: @, advanced past the tag content: text from scan up to tag #-- 2 -- # [ if content is None -> ... # else if tag has any attributes -> # Log() +:= error message # else -> ... ] scan: @, advanced past the tag content: text from scan up to tag Log(): @+(error message) #-- TARGET -- OK [ if scan contains a valid tag somewhere before EOF -> ... else -> scan := scan advanced past tag or to EOF Log() +:= error message ] # - - - B o d y . _ _ p a r s e A u t h o r T a g - - - #### Case 3: scan contains a valid tag #-- 1 -- # [ if scan contains a valid tag before EOF -> # scan := scan advanced past the first such tag # content := text from scan up to tag # else -> ... ] scan: @, advanced past first tag content: text from scan up to tag #-- 2 -- # [ if content is None -> ... # else if tag has any attributes -> ... # else -> # self.author := content ] scan: @, advanced past first tag content: text from scan up to tag self.author: text from scan up to tag #-- TARGET -- OK [ if scan contains a valid tag somewhere before EOF -> scan := scan advanced past the first such tag self.author := text from scan up to the tag else -> ... ] # - - - B o d y . _ _ p a r s e G T a g - - - #### Case 1: tag is not a valid G tag #-- 1 -- # [ if tag has one ID attribute that names a valid short name # in self.topic.plan -> ... # else -> # Log() +:= error message(s) # return ] Log(): @+(error message) return #-- TARGET -- OK [ if tag is a valid tag -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e G T a g - - - #### Case 2: tag is a valid G tag #-- 1 -- # [ if tag has one ID attribute that names a valid short name # in self.topic.plan -> # target := a Target object representing that short name # else -> ... ] target: a Target object representing tag's ID attribute in self.topic.plan #-- 2 -- # [ self.text +:= (link to target) + (title of target) + "" ] target: a Target object representing tag's ID attribute in self.topic.plan self.text: @+(link to tag's ID in self.topic.plan)+(title of tag's ID in self.topic.plan)+"" #-- TARGET -- OK [ if tag is a valid tag -> self.text +:= (link to target topic of tag) + (title of target topic of tag) + "" else -> ... ] # - - - B o d y . _ _ p a r s e H e a d T a g - - - (trivial, by inspection) # - - - B o d y . _ _ p a r s e N e x t T a g - - - #### Case 1: tag is not a valid NEXT tag #-- 1 -- # [ if tag has one ID attribute whose value is a short name # found in self.topic.plan -> ... # else if tag has one NONE attribute with no value -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if tag is a valid tag of the form -> ... else if tag has the form -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e N e x t T a g - - - #### Case 2: tag has a NONE attribute with no value #-- 1 -- # [ if tag has one ID attribute whose value is a short name # found in self.topic.plan -> ... # else if tag has one NONE attribute with no value -> # self.enext := None # else -> ... ] self.enext: None #-- TARGET -- OK [ if tag is a valid tag of the form -> ... else if tag has the form -> self.enext := None else -> ... ] # - - - B o d y . _ _ p a r s e N e x t T a g - - - #### Case 3: tag has an ID attribute whose value is a short name in #### self.topic.plan #-- 1 -- # [ if tag has one ID attribute whose value is a short name # found in self.topic.plan -> # self.enext := a Target object representing that short name # else ... ] self.enext: a Target object representing the topic in self.topic.plan corresponding to tag's ID attribute #-- TARGET -- OK [ if tag is a valid tag of the form -> self.enext := a Target object representing foo else ... ] # - - - B o d y . _ _ p a r s e P r e v T a g - - - #### Case 1: tag is not valid #-- 1 -- # [ if tag has one ID attribute whose value is a short name # found in self.topic.plan -> ... # else if tag has one NONE attribute with no value -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if tag is a valid tag of the form -> ... else if tag has the form -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e P r e v T a g - - - #### Case 2: tag has one attribute "NONE" with no value #-- 1 -- # [ if tag has one ID attribute whose value is a short name # found in self.topic.plan -> ... # else if tag has one NONE attribute with no value -> # self.eprev := None # else -> ... ] self.eprev: None #-- TARGET -- OK [ if tag is a valid tag of the form -> ... else if tag has the form -> self.eprev := None else -> ... ] # - - - B o d y . _ _ p a r s e P r e v T a g - - - #### Case 3: tag has one attribute "ID" whose value is a short name #### found in self.topic.plan #-- 1 -- # [ if tag has one ID attribute whose value is a short name # found in self.topic.plan -> # self.eprev := a Target object representing that short name # else ... ] self.eprev: a Target object representing tag's ID attribute's value in self.topic.plan #-- TARGET -- OK [ if tag is a valid tag of the form -> self.eprev := a Target object representing foo else ... ] # - - - B o d y . _ _ p a r s e R T a g - - - #### Case 1: tag does not an ID attribute value that is a short name #### in self.topic.plan #-- 1 -- # [ if tag has one ID attribute that names a valid short name # in self.topic.plan -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if tag is a valid tag of the form -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e R T a g - - - #### Case 2: tag has an ID attribute value that is a short name #### in self.topic.plan #-- 1 -- # [ if tag has one ID attribute that names a valid short name # in self.topic.plan -> # target := a Target object representing that short name # else -> ... ] target: a Target object representing tag's ID attribute's value in self.topic.plan #-- 2 -- # [ self.text +:= (link to target) + "`" + (title of target) # + "'" ] target: a Target object representing tag's ID attribute's value in self.topic.plan self.text: @+(link to tag's ID attribute's value in self.topic.plan)+ "`"+(title of tag's ID attribute's title in self.topic.plan)+"'" #-- TARGET -- OK [ if tag is a valid tag of the form -> self.text +:= (link to foo) + (title of foo) + "" else -> ... ] # - - - B o d y . _ _ p a r s e R R T a g - - - #### Case 1: scan does not contain an tag #-- 1 -- # [ lineNo := current line number from scan ] lineNo: @(scan.lineNo) #-- 2 -- # [ if scan contains an tag before EOF -> ... # else -> # scan := scan advanced to EOF # Log() +:= error message # return ] lineNo: @(scan.lineNo) scan: @, advanced to EOF Log(): @+(error message) #-- TARGET -- OK [ if tag does not have the form where foo is a short name defined in self.topic.plan -> ... else if scan does not contain a tag before EOF -> scan := scan advanced to EOF Log() +:= error message else -> ... ] # - - - B o d y . _ _ p a r s e R R T a g - - - #### Case 2: tag does not have ID="foo" where foo is a short name #### defined in self.topic.plan, but there is an tag in scan #-- 1 -- # [ lineNo := current line number from scan ] lineNo: @(scan.lineNo) #-- 2 -- # [ if scan contains an tag before EOF -> # scan := scan advanced past the next tag # linkText := text from scan up to next tag # else -> ... ] # target := a Target object representing that short name lineNo: @(scan.lineNo) scan: @, advanced past the next tag linkText: text from @(scan) up to next tag #-- 3 -- # [ if tag has one ID attribute that names a short name found in # self.topic.plan -> ... # else -> # Log() +:= error message # return ] lineNo: @(scan.lineNo) scan: @, advanced past the next tag linkText: text from @(scan) up to next tag Log(): @+(error message) return #-- TARGET -- OK [ if tag does not have the form where foo is a short name defined in self.topic.plan -> scan := scan advanced past next tag, or to EOF Log() +:= error message else ... ] # - - - B o d y . _ _ p a r s e R R T a g - - - #### Case 3: tag does not have ID="foo" where foo is a short name #### defined in self.topic.plan, and there is no tag in scan #-- 1 -- # [ lineNo := current line number from scan ] lineNo: @(scan.lineNo) #-- 2 -- # [ if scan contains an tag before EOF -> ... # else -> # scan := scan advanced to EOF # Log() +:= error message # return ] lineNo: @(scan.lineNo) scan: @, advanced to EOF Log(): @+(error message) return #-- TARGET -- OK [ if tag does not have the form where foo is a short name defined in self.topic.plan -> Log() +:= error message scan := scan advanced past next tag, or to EOF else ... ] # - - - B o d y . _ _ p a r s e R R T a g - - - #### Case 4: tag has ID="foo" where foo is a short name #### defined in self.topic.plan, and there is an tag in scan #-- 1 -- # [ lineNo := current line number from scan ] lineNo: @(scan.lineNo) #-- 2 -- # [ if scan contains an tag before EOF -> # scan := scan advanced past the next tag # linkText := text from scan up to next tag # else -> ... ] lineNo: @(scan.lineNo) scan: @, advanced past next tag linkText: text from @(scan) up to next tag #-- 3 -- # [ if tag has one ID attribute that names a short name found in # self.topic.plan -> # target := a Target object representing that short name # else -> ... ] lineNo: @(scan.lineNo) scan: @, advanced past next tag linkText: text from @(scan) up to next tag target: a Target object representing tag.id's value as a short name #-- 4 -- # [ self.text +:= (link to target) + (linkText) + "" ] lineNo: @(scan.lineNo) scan: @, advanced past next tag linkText: text from @(scan) up to next tag target: a Target object representing tag.id's value as a short name self.text: @+(link to tag.id's value as a short name)+ (text from @(scan) up to next tag)+"" #-- 5 -- # [ self.topic.plan := self.plan with a LinkVar added with .text= # (text from scan up to next tag), # .shortName=foo, and .lineNo=scan.lineNo ] lineNo: @(scan.lineNo) scan: @, advanced past next tag linkText: text from @(scan) up to next tag target: a Target object representing tag.id's value as a short name self.text: @+(link to tag.id's value as a short name)+ (text from @(scan) up to next tag)+"" self.topic.plan: @ with a LinkVar added with .text=(text from @(scan) up to next tag), .shortName=self.topic.shortName, and lineNo=@(scan.lineNo) #-- TARGET -- OK [ if tag does not have the form where foo is a short name defined in self.topic.plan -> ... else if scan does not contain a tag before EOF -> ... else -> scan := scan advanced past the next tag self.text +:= (link to foo) + (text from scan up to next tag) + "" self.topic.plan := self.plan with a LinkVar added with .text= (text from scan up to next tag), .shortName=foo, and .lineNo=scan.lineNo ] # - - - B o d y . _ _ p a r s e S e e T a g - - - #### Case 1: tag has the form where foo is a short name #### found in self.topic.plan #-- 1 -- # [ if tag has one ID attribute whose value is a short name found # in self.topic.plan -> # target := a Target object representing that short name # else if tag has one NONE attribute with no value -> ... # else -> ... ] target: a Target object representing tag's ID attribute as a short name in self.topic.plan #-- 2 -- if target is None: self.seeList = [] else: self.seeList.append ( target ) target: a Target object representing tag's ID attribute as a short name in self.topic.plan self.seeList := self.seeList + a Target object representing tag's ID attribute as a short name in self.topic.plan #-- TARGET -- OK [ if tag has the form where foo is a short name found in self.topic.plan -> self.seeList +:= a Target object representing foo else if tag has the form -> ... else -> ... ] # - - - B o d y . _ _ p a r s e S e e T a g - - - #### Case 2: tag has the form #-- 1 -- # [ if tag has one ID attribute whose value is a short name found # in self.topic.plan -> ... # else if tag has one NONE attribute with no value -> # target := None # else -> ... ] target: None #-- 2 -- if target is None: self.seeList = [] else: self.seeList.append ( target ) target: None self.seeList: a new, empty list #-- TARGET -- OK [ if tag has the form where foo is a short name found in self.topic.plan -> ... else if tag has the form -> self.seeList := [] else -> ... ] # - - - B o d y . _ _ p a r s e S e e T a g - - - #### Case 3: (tag does not have form where foo is a #### shortname in self.topic.plan) and (tag does not have form #-- 1 -- # [ if tag has one ID attribute whose value is a short name found # in self.topic.plan -> ... # else if tag has one NONE attribute with no value -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if tag has the form where foo is a short name found in self.topic.plan -> ... else if tag has the form -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e T e m p l a t e T a g - - - #### Case 1: tag has one ID attribute naming a valid template file #-- 1 -- # [ if tag has one attribute -> # tagAttr := a TagAttr object representing that attribute # else -> ... ] tagAttr: the sole TagAttr in tag #-- 2 -- # [ if tagAttr has name "id" and a value -> # path := that value # else -> # Log() +:= error message # return ] tagAttr: the sole TagAttr in tag path: the value of the sole attribute in tag #-- 3 -- # [ if path names a valid template file relative to the starting # directory -> # template := a Template object representing that file # else -> # Log() +:= error message # return ] tagAttr: the sole TagAttr in tag path: the value of the sole attribute in tag template: a Template representing the file named by the sole attr. of tag #-- 4 -- self.etemplate = template tagAttr: the sole TagAttr in tag path: the value of the sole attribute in tag template: a Template representing the file named by the sole attr. of tag self.etemplate: a Template representing the file named by the sole attribute of tag #-- TARGET -- OK [ if tag has one ID attribute that names a valid template file, relative to the starting directory -> self := self with its effective template changed to that template as a Template object else -> ... ] # - - - B o d y . _ _ p a r s e T e m p l a t e T a g - - - #### Case 2: tag does not have exactly one attribute #-- 1 -- # [ if tag has one attribute -> # tagAttr := a TagAttr object representing that attribute # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if tag has one ID attribute that names a valid template file, relative to the starting directory -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e T e m p l a t e T a g - - - #### Case 3: tag has one attribute, but its name is not "id" or #### it has no value #-- 1 -- # [ if tag has one attribute -> # tagAttr := a TagAttr object representing that attribute # else -> # Log() +:= error message # return ] tagAttr: a TagAttr object representing tag's one attribute #-- 2 -- # [ if tagAttr has name "id" and a value -> ... # else -> # Log() +:= error message # return ] tagAttr: a TagAttr object representing tag's one attribute Log(): @+(error message) return #-- TARGET -- OK [ if tag has one ID attribute that names a valid template file, relative to the starting directory -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e T e m p l a t e T a g - - - #### Case 4: tag has one "id" attribute with a value, but that value #### does not name a valid template file #-- 1 -- # [ if tag has one attribute -> # tagAttr := a TagAttr object representing that attribute # else -> ... ] tagAttr: a TagAttr obj. repr. tag's one attribute #-- 2 -- # [ if tagAttr has name "id" and a value -> # path := that value # else -> # Log() +:= error message # return ] tagAttr: a TagAttr obj. repr. tag's one attribute path: the value of tag's one attribute #-- 3 -- # [ if path names a valid template file relative to the starting # directory -> ... # else -> # Log() +:= error message # return ] tagAttr: a TagAttr obj. repr. tag's one attribute path: the value of tag's one attribute Log(): @+(error message) return #-- TARGET -- OK [ if tag has one ID attribute that names a valid template file, relative to the starting directory -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e U p d a t e d T a g - - - #### Case 1: number of tag's attributes is not one #-- 1 -- # [ if tag has exactly one attribute -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if tag has one ID attribute whose value is a valid RCS date -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e U p d a t e d T a g - - - #### Case 2: tag has one attribute but its name is not `date' -> #-- 1 -- # [ if tag has exactly one attribute -> # tagAttr := a TagAttr representing that attribute # else -> ... ] tagAttr: a TagAttr repr. tag's one attribute #-- 2 -- # [ if tagAttr.name is not "date" -> # Log() +:= error message # return # else -> I ] tagAttr: a TagAttr repr. tag's one attribute Log(): @+(error message) return #-- TARGET -- OK [ if tag has one ID attribute whose value is a valid RCS date ->... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e U p d a t e d T a g - - - #### Case 3: tag has one attribute "date" but it doesn't look like #### an RCS date tag #-- 1 -- # [ if tag has exactly one attribute -> # tagAttr := a TagAttr representing that attribute # else -> ... ] tagAttr: a TagAttr repr. tag's one attribute #-- 2 -- # [ if tagAttr.name is not "date" -> # Log() +:= error message # return # else -> I ] tagAttr: a TagAttr repr. tag's one attribute #-- 3 -- # [ if tagAttr.value looks like a checked-in file's timestamp -> ... # else -> # Log() +:= error message # return ] tagAttr: a TagAttr repr. tag's one attribute Log(): @+(error message) return #-- TARGET -- OK [ if tag has one ID attribute whose value is a valid RCS date -> ... else -> Log() +:= error message ] # - - - B o d y . _ _ p a r s e U p d a t e d T a g - - - #### Case 3: tag has one attribute "date" whose value looks like #### an RCS date tag #-- 1 -- # [ if tag has exactly one attribute -> # tagAttr := a TagAttr representing that attribute # else -> # Log() +:= error message # return ] tagAttr: a TagAttr representing tag's one attribute #-- 2 -- # [ if tagAttr.name is not "date" -> # Log() +:= error message # return # else -> I ] tagAttr: a TagAttr representing tag's one attribute #-- 3 -- # [ if tagAttr.value looks like a checked-in file's timestamp, # with "Date: " followed later by "$" -> # timestamp := everything between "Date" and "$" from # tagAttr.value # else -> ... ] tagAttr: a TagAttr representing tag's one attribute timestamp: Everything between "Date" and the next "$" from the value of tag's one attribute #-- 4 -- self.updated = timestamp[2:] tagAttr: a TagAttr representing tag's one attribute timestamp: Everything between "Date" and the next "$" from the value of tag's one attribute self.updated: Everything between "Date: " and the next "$" from the value of tag's one attribute #-- TARGET -- OK [ if tag has one ID attribute whose value is a valid RCS date -> self.updated := the timestamp from that tag else -> ... ] # - - - B o d y . _ _ f i n d T a r g e t - - - #### Case 1: number of tag's attributes is not one #-- 1 -- # [ if tag has one attribute -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if (tag is an SGMLTag object) and (scan is a Scan object) -> if tag has one ID attribute that names a valid short name in self.topic.plan -> ... else -> Log() +:= error message(s) return ] # - - - B o d y . _ _ f i n d T a r g e t - - - #### Case 2: tag has one attribute, but it isn't "id" or has no value #-- 1 -- # [ if tag has one attribute -> # tagAttr := a TagAttr object representing that attribute # else -> # Log() +:= error message # return ] tagAttr: a TagAttr repr. tag's one attribute #-- 2 -- # [ if tagAttr has name "id" and a value -> # value := that value # else -> # Log() +:= error message # return ] tagAttr: a TagAttr repr. tag's one attribute Log(): @+(error message) return #-- TARGET -- OK [ if (tag is an SGMLTag object) and (scan is a Scan object) -> if tag has one ID attribute that names a valid short name in self.topic.plan -> ... else -> Log() +:= error message(s) return ] # - - - B o d y . _ _ f i n d T a r g e t - - - #### Case 3: tag has one "id" attribute with a value, but the value #### (up to the first "#" if there is one) is not a valid short name #### in self.topic.plan #-- 1 -- # [ if tag has one attribute -> # tagAttr := a TagAttr object representing that attribute # else -> ... ] tagAttr: a TagAttr repr. tag's one attribute #-- 2 -- # [ if tagAttr has name "id" and a value -> # value := that value # else -> # Log() +:= error message # return ] tagAttr: a TagAttr repr. tag's one attribute value: the value of tag's one attribute #-- 3 -- # [ if value, up to its first "#" if it contains one, is a valid # short name in self.topic.plan -> ... # else -> # Log() +:= error message # return ] tagAttr: a TagAttr repr. tag's one attribute value: the value of tag's one attribute Log(): @+(error message) return #-- TARGET -- OK [ if (tag is an SGMLTag object) and (scan is a Scan object) -> if tag has one ID attribute that names a valid short name in self.topic.plan -> ... else -> Log() +:= error message(s) return ] # - - - B o d y . _ _ f i n d T a r g e t - - - #### Case 4: tag has one "id" attribute with a value, and the value #### (up to the first "#" if there is one) is a valid short name #### in self.topic.plan #-- 1 -- # [ if tag has one attribute -> # tagAttr := a TagAttr object representing that attribute # else -> # Log() +:= error message # return ] tagAttr: a TagAttr representing tag's one attribute #-- 2 -- # [ if tagAttr has name "id" and a value -> # value := that value # else -> # Log() +:= error message # return ] tagAttr: a TagAttr representing tag's one attribute value: the value of tag's one attribute #-- 3 -- # [ if value, up to its first "#" if it contains one, is a valid # short name in self.topic.plan -> # target := a Target object for that short name, with an # anchor from value if it contains "#" # else -> # Log() +:= error message # return ] tagAttr: a TagAttr representing tag's one attribute value: the value of tag's one attribute target: a Target object whose page is the value of tag's one attribute, up to the first "#" if it has one, and whose anchor is the part of that value from the first "#" to the end if there is one, or None if there is no "#" #-- 4 -- return target return a Target object whose page is the value of tag's one attribute, up to the first "#" if it has one, and whose anchor is the part of that value from the first "#" to the end if there is one, or None if there is no "#" #-- TARGET -- OK [ if (tag is an SGMLTag object) and (scan is a Scan object) -> if tag has one ID attribute that names a valid short name in self.topic.plan -> return a Target object representing that short name and optional anchor else -> ... ] # - - - B o d y . _ _ f i n d E f f e c t i v e T a r g e t - - - #### Case 1: number of tag's attributes is not one #-- 1 -- # [ if number of tag's attributes is not one -> # Log() +:= error message # return # else -> ... ] Log(): @+(error message) return #-- TARGET -- OK [ if (tag is an SGMLTag object) -> if tag has one ID attribute whose value is a short name found in self.topic.plan -> ... else if tag has one NONE attribute with no value -> ... else -> Log() +:= error message raise ValueError ] # - - - B o d y . _ _ f i n d E f f e c t i v e T a r g e t - - - #### Case 2: tag has one "none" attribute #-- 1 -- # [ if tag has one attribute with name "none" -> # return None # else -> I ] return None #-- TARGET -- OK [ if (tag is an SGMLTag object) -> if tag has one ID attribute whose value is a short name found in self.topic.plan -> ... else if tag has one NONE attribute -> return None else -> ... ] # - - - B o d y . _ _ f i n d E f f e c t i v e T a r g e t - - - #### Case 3: (tag has one attribute but its name is not "id" or "none") #-- 1 -- # [ if number of tag's attributes is not one -> ... # else -> # tagAttr := a TagAttr repr. tag's first attribute ] tagAttr: a TagAttr repr. tag's one attribute #-- 2 -- # [ if tagAttr's name is "none" -> # return None # else -> I ] tagAttr: a TagAttr repr. tag's one attribute #-- 3 -- # [ if tagAttr has name "id" and a value -> ... # else -> # Log() +:= error message # return ] tagAttr: a TagAttr repr. tag's one attribute Log(): @+(error message) return #-- TARGET -- OK [ if (tag is an SGMLTag object) -> if tag has one ID attribute whose value is a short name found in self.topic.plan -> ... else if tag has one NONE attribute -> ... else -> Log() +:= error message raise ValueError ] # - - - B o d y . _ _ f i n d E f f e c t i v e T a r g e t - - - #### Case 4: (tag has one "id" attribute with a value but that value #### is not a short reference in self.topic.plan (with optional anchor) #-- 1 -- # [ if number of tag's attributes is not one -> # Log() +:= error message # return # else -> # tagAttr := a TagAttr repr. tag's first attribute ] tagAttr: A TagAttr representing tag's one attribute #-- 2 -- # [ if tagAttr's name is "none" -> # return None # else -> I ] tagAttr: A TagAttr representing tag's one attribute #-- 3 -- # [ if tagAttr has name "id" and a value -> # value := that value # else -> ... ] tagAttr: A TagAttr representing tag's one attribute value: the value of tag's one attribute #-- 4 -- # [ if value, up to its first "#" if it contains one, is a valid # short name in self.topic.plan -> ... # else -> # Log() +:= error message # raise ValueError ] tagAttr: A TagAttr representing tag's one attribute value: the value of tag's one attribute Log(): @+(error message) raise ValueError #-- TARGET -- OK [ if (tag is an SGMLTag object) -> if tag has one ID attribute whose value is a short name found in self.topic.plan -> ... else if tag has one NONE attribute -> ... else -> Log() +:= error message raise ValueError ] # - - - B o d y . _ _ f i n d E f f e c t i v e T a r g e t - - - #### Case 5: (tag has one "id" attribute with a value and that value #### is a short reference in self.topic.plan (with optional anchor) #-- 1 -- # [ if number of tag's attributes is not one -> # Log() +:= error message # return # else -> # tagAttr := a TagAttr repr. tag's first attribute ] tagAttr: a TagAttr repr. tag's one attribute #-- 2 -- # [ if tagAttr's name is "none" -> # return None # else -> I ] tagAttr: a TagAttr repr. tag's one attribute #-- 3 -- # [ if tagAttr has name "id" and a value -> # value := that value # else -> # Log() +:= error message # return ] tagAttr: a TagAttr repr. tag's one attribute value: the value from tag's one attribute #-- 4 -- # [ if value, up to its first "#" if it contains one, is a valid # short name in self.topic.plan -> # target := a Target object for that short name, with an # anchor from value if it contains "#" # else -> ... ] tagAttr: a TagAttr repr. tag's one attribute value: the value from tag's one attribute target: a Target whose short name comes from the value of tag's one attribute, up to the first "#" if any, and whose optional anchor consists of the first "#" through the end of that value, if a "#" is present #-- 5 -- return target return a Target whose short name comes from the value of tag's one attribute, up to the first "#" if any, and whose optional anchor consists of the first "#" through the end of that value, if a "#" is present #-- TARGET -- OK [ if (tag is an SGMLTag object) -> if tag has one ID attribute whose value is a short name found in self.topic.plan, with optional anchor -> return a Target object representing that short name and optional anchor else if tag has one NONE attribute -> ... else -> ... ] # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### Case 1: scan does not contain a tag with identifier gi before #### the next malformed tag #-- 1 -- # [ errCount := count of errors in the Log() object # L := an empty list # done := 0 # lowTarget := gi, lowercased ] errCount: @(Log().count()) L: an empty list done: 0 lowTarget: lowercase(gi) #-- 2 -- # [ if scan contains optional text and/or tags followed by # a closing tag with identifier gi -> ... # else -> # scan := scan advanced past the first malformed tag or EOF # Log() +:= error message(s) # L +:= text and valid tags up to the first malformed # tag or EOF ] errCount: @(Log().count()) L: [text and valid tags up to the first malformed tag in scan done: 0 lowTarget: lowercase(gi) scan: @, advanced past the first malformed tag Log(): @+(error(s)) #-- 3 -- # [ if errCount < (count of errors from Log() ) -> # return None # else -> ... ] errCount: @(Log().count()) L: [text and valid tags up to the first malformed tag in scan done: 0 lowTarget: lowercase(gi) scan: @, advanced past the first malformed tag Log(): @+(error(s)) return None #-- TARGET -- OK [ if (scan is a Scan object) and (gi is a tag identifier) -> if scan contains a closing tag with identifier gi -> ... else -> scan := scan advanced past a malformed tag or to EOF, whichever is first Log() +:= error message return None ] # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### Case 2: scan does not contain a tag with identifier gi before EOF #-- 1 -- # [ errCount := count of errors in the Log() object # L := an empty list # done := 0 # lowTarget := gi, lowercased ] errCount: @(Log().count()) L: [] done: 0 lowTarget: lowercase(gi) #-- 2 -- # [ if scan contains optional text and/or tags followed by # a closing tag with identifier gi -> ... # else -> # scan := scan advanced past the first malformed tag or EOF # Log() +:= error message(s) # L +:= text and valid tags up to the first malformed # tag or EOF ] errCount: @(Log().count()) L: [text and valid tags remaining in scan] done: 0 lowTarget: lowercase(gi) scan: scan advanced to EOF Log(): @+(error(s)) #-- 3 -- # [ if errCount < (count of errors from Log() ) -> # return None # else -> # return elements of L concatenated ] errCount: @(Log().count()) L: [text and valid tags remaining in scan] done: 0 lowTarget: lowercase(gi) scan: scan advanced to EOF Log(): @+(error(s)) return None #-- TARGET -- OK [ if (scan is a Scan object) and (gi is a tag identifier) -> if scan contains a closing tag with identifier gi -> ... else -> scan := scan advanced past a malformed tag or to EOF, whichever is first Log() +:= error message return None ] # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### Case 3: scan contains a closing tag with identifier gi #-- 1 -- # [ errCount := count of errors in the Log() object # L := an empty list # done := 0 # lowTarget := gi, lowercased ] errCount: @(Log().count()) L: [] done: 0 lowTarget: lowercase(gi) #-- 2 -- # [ if scan contains optional text and/or tags followed by # a closing tag with identifier gi -> # scan := scan advanced past the first such closing tag # L +:= (text from scan up to the closing tag) # else -> ... ] errCount: @(Log().count()) L: [text from @(scan) up to the first closing tag with identifier gi] done: 0 lowTarget: lowercase(gi) scan: @, advanced past the first closing tag with identifier gi #-- 3 -- # [ if errCount < (count of errors from Log() ) -> ... # else -> # return elements of L concatenated ] return [text from @(scan) up to the first closing tag with identifier gi] #-- TARGET -- OK [ if (scan is a Scan object) and (gi is a tag identifier) -> if scan contains a closing tag with identifier gi -> scan := scan advanced past the first such closing tag return text from scan up to the closing tag else -> ... ] # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### While, case 1: scan is at EOF L: @ done: 0 scan: @ done = self.__gropeForCloser ( scan, L, gi ) L: @ done: 1 scan: @ #-- TARGET -- OK # [ if scan contains optional text and/or tags followed by # a closing tag with identifier gi -> ... # else -> # scan := scan advanced past the first malformed tag or EOF # Log() +:= error message(s) # L +:= text and valid tags up to the first malformed # tag or EOF ] # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### While, case 2: scan starts with a valid close tag of type (gi) L: @ done: 0 scan: @ done = self.__gropeForCloser ( scan, L, gi ) L: @ done: 1 scan: @, advanced past closing tag of type gi #-- TARGET -- OK #-- 2 -- # [ if scan contains optional text and/or tags followed by # a closing tag with identifier gi -> # scan := scan advanced past the first such closing tag # L +:= (text from scan up to the closing tag) # else -> ... ] # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### While, case 3: scan starts with a valid tag but not type gi L: @ done: 0 scan: @ done = self.__gropeForCloser ( scan, L, gi ) L: @+(text equivalent of tag at start of scan) done: 0 scan: @, advanced past tag at start #-- TARGET -- OK by inspection # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### While, case 4: scan starts with a malformed tag L: @ done: 0 scan: @ done = self.__gropeForCloser ( scan, L, gi ) L: @ done: 0 scan: @, advanced past malformed tag or to EOF #-- TARGET -- OK by inspection # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### While, case 5: line in scan contains an SGML_TAG_OPEN L: @ done: 0 scan: @ done = self.__gropeForCloser ( scan, L, gi ) L: @+(text up to next SGML_TAG_OPEN) done: 0 scan: @, advanced up to next SGML_TAG_OPEN #-- TARGET -- OK by inspection # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### While, case 6: line in scan contains no SGML_TAG_OPEN and #### is last line in file L: @ done: 0 scan: @ done = self.__gropeForCloser ( scan, L, gi ) L: @+(text from scan up to EOF) done: 1 scan: @, advanced to EOF #-- TARGET -- OK by inspection # - - - B o d y . _ _ p a r s e T o C l o s i n g T a g - - - #### While, case 7: line in scan contains no SGML_TAG_OPEN and #### is not last line in file L: @ done: 0 scan: @ done = self.__gropeForCloser ( scan, L, gi ) L: @+(remainder of line in scan+"\n") done: 0 scan: @, advanced to start of next line #-- TARGET -- OK by inspection # - - - B o d y . _ _ g r o p e F o r C l o s e r - - - #### Case 1: scan is at EOF #-- 1 -- # [ if scan is at EOF -> return 1 # else -> I ] return 1 #-- TARGET -- OK [ if scan is at EOF -> return 1 else ... ] # - - - B o d y . _ _ g r o p e F o r C l o s e r - - - #### Case 2: scan starts with a valid closing tag of type (gi) #-- 1 -- # [ if scan is at EOF -> return 1 # else -> I ] I #-- 2 -- # [ if scan starts with SGML_TAG_OPEN -> # pastOpen := position past that character # else -> ... ] pastOpen: (position of scan)+1 #-- 3 -- if pastOpen is None: ... else: #-- 3.2 -- # [ if scan starts with SGML_TAG_OPEN -> # if scan starts with a valid closing tag of type gi -> # scan := scan advanced past that tag # return 1 # else ... ] pastOpen: (position of scan)+1 scan: @, advanced past the leading tag return 1 #-- TARGET -- OK [ if scan is at EOF -> ... else if scan starts with a valid close tag of type (gi) -> scan := scan advanced past that tag return 1 else ... ] # - - - B o d y . _ _ g r o p e F o r C l o s e r - - - #### Case 3: scan starts with a malformed tag #-- 1 -- # [ if scan is at EOF -> return 1 # else -> I ] #-- 2 -- # [ if scan starts with SGML_TAG_OPEN -> # pastOpen := position past that character # else -> # pastOpen := None ] pastOpen: (position(@(scan))+1 #-- 3 -- if pastOpen is None: ... else: #-- 3.2 -- # [ if scan starts with SGML_TAG_OPEN -> # if scan starts with a valid closing tag of type gi -> ... # else if scan starts with a badly formed tag -> # scan := scan advanced past that tag or to EOF # Log() +:= error message(s) # return 1 # else -> ... ] pastOpen: (position(@(scan))+1 scan: @, advanced past badly formed tag or to EOF Log(): @+(error(s)) return 1 #-- TARGET -- OK [ if scan is at EOF -> ... else if scan starts with a valid close tag of type (gi) -> ... else if scan starts with a valid tag -> ... else if scan starts with a malformed tag -> scan := scan advanced past that tag or to EOF Log() +:= error message(s) return 0 else ... ] # - - - B o d y . _ _ g r o p e F o r C l o s e r - - - #### Case 4: line in scan has an SGML_TAG_OPEN in it somewhere #-- 1 -- # [ if scan is at EOF -> return 1 # else -> I ] #-- 2 -- # [ if scan starts with SGML_TAG_OPEN -> # pastOpen := position past that character # else -> # pastOpen := None ] pastOpen: None #-- 3 -- if pastOpen is None: #-- 3.1 -- # [ if there is an SGML_TAG_OPEN anywhere on the current line # of scan -> # scan := scan advanced up to the first SGML_TAG_OPEN # L +:= text up the first SGML_TAG_OPEN # return 0 # else ... ] else: ... pastOpen: None scan: @, advanced up to the first SGML_TAG_OPEN L: @+(text up to the first SGML_TAG_OPEN in scan) return 0 #-- TARGET -- OK [ if scan is at EOF -> ... else if scan starts with a valid close tag of type (gi) -> ... else if scan starts with a valid tag -> ... else if scan starts with a malformed tag -> ... else if the line in scan has an SGML_TAG_OPEN anywhere in it -> scan := scan advanced up to the next SGML_TAG_OPEN L +:= text up to the next SGML_TAG_OPEN return 0 else ... ] # - - - B o d y . _ _ g r o p e F o r C l o s e r - - - #### Case 5: line in scan has no SGML_TAG_OPEN and is last line #-- 1 -- # [ if scan is at EOF -> return 1 # else -> I ] #-- 2 -- # [ if scan starts with SGML_TAG_OPEN -> # pastOpen := position past that character # else -> # pastOpen := None ] pastOpen: None #-- 3 -- if pastOpen is None: #-- 3.1 -- # [ if there is an SGML_TAG_OPEN anywhere on the current line # of scan -> ... # else if line in scan is last in file -> # scan := scan advanced to EOF # L +:= (text up to EOF) + "\n" # return 1 # else -> ... ] else: ... pastOpen: None scan: @, advanced to EOF L: @+(text from scan up to EOF) return 1 #-- TARGET -- OK [ if scan is at EOF -> ... else if scan starts with a valid close tag of type (gi) -> ... else if scan starts with a valid tag -> ... else if scan starts with a malformed tag -> ... else if the line in scan has an SGML_TAG_OPEN anywhere in it -> ... else if line in scan is the last in the file -> scan := scan advanced to EOF L +:= text from scan up to EOF return 1 else -> ... ] # - - - B o d y . _ _ g r o p e F o r C l o s e r - - - #### Case 6: line in scan has no SGML_TAG_OPEN and is not last line #-- 1 -- # [ if scan is at EOF -> return 1 # else -> I ] #-- 2 -- # [ if scan starts with SGML_TAG_OPEN -> # pastOpen := position past that character # else -> # pastOpen := None ] pastOpen: None #-- 3 -- if pastOpen is None: #-- 3.1 -- # [ if there is an SGML_TAG_OPEN anywhere on the current line # of scan -> ... # else if line in scan is last in file -> ... # else -> # scan := scan advanced to the start of the next line # L +:= (text up to end of line) + "\n" # return 0 ] else: ... pastOpen: None scan: @, advanced to start of next line L: @+(text from scan up to end of line)+"\n" return 0 #-- TARGET -- OK [ if scan is at EOF -> ... else if scan starts with a valid close tag of type (gi) -> ... else if scan starts with a valid tag -> ... else if scan starts with a malformed tag -> ... else if the line in scan has an SGML_TAG_OPEN anywhere in it -> ... else if line in scan is the last in the file -> ... else -> scan := scan advanced to the start of the next line L +:= (remainder of line in scan) + "\n" return 0 ] # - - - B o d y . _ _ g r o p e N o n T a g - - - #### Case 1: line in scan contains at least one SGML_TAG_OPEN #-- 1 -- # [ if there is an SGML_TAG_OPEN anywhere in the line in scan -> # endp := position at the start of the first SGML_TAG_OPEN # else -> ... ] endp: position before first SGML_TAG_OPEN in @(scan) #-- 2 -- if endp is None: ... else: #-- 2.2 -- # [ scan := scan advanced to endp # L +:= (text up to endp) ] endp: position before first SGML_TAG_OPEN in @(scan) scan: @, advanced up to first SGML_TAG_OPEN in line L: @+(text up to first SGML_TAG_OPEN in @(scan)) #-- 3 -- if scan.atEndFile: return 1 else: return 0 endp: position before first SGML_TAG_OPEN in @(scan) scan: @, advanced up to first SGML_TAG_OPEN in line L: @+(text up to first SGML_TAG_OPEN in @(scan)) return 0 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) -> if there is an SGML_TAG_OPEN anywhere on the current line of scan -> scan := scan advanced up to the first SGML_TAG_OPEN L +:= text up the first SGML_TAG_OPEN return 0 else ... ] # - - - B o d y . _ _ g r o p e N o n T a g - - - #### Case 2: line in scan contains no SGML_TAG_OPEN and is last line #-- 1 -- # [ if there is an SGML_TAG_OPEN anywhere in the line in scan -> # endp := position at the start of the first SGML_TAG_OPEN # else -> # endp := None ] endp: None #-- 2 -- if endp is None: #-- 2.1 -- # [ scan := scan advanced to the next line, or EOF # L +:= (text up to end of line in scan) + "\n" ] endp: None scan: @, advanced to next line L: @+(text from scan to end of line)+"\n" #-- 3 -- if scan.atEndFile: return 1 else: return 0 endp: None scan: @, advanced to next line L: @+(text from scan to end of line)+"\n" return 1 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) -> if there is an SGML_TAG_OPEN anywhere on the current line of scan -> ... else if line in scan is last in file -> scan := scan advanced to EOF L +:= (text up to EOF) + "\n" return 1 else -> ... ] # - - - B o d y . _ _ g r o p e N o n T a g - - - #### Case 3: line in scan contains no SGML_TAG_OPEN and is not last line #-- 1 -- # [ if there is an SGML_TAG_OPEN anywhere in the line in scan -> # endp := position at the start of the first SGML_TAG_OPEN # else -> # endp := None ] endp: None #-- 2 -- if endp is None: #-- 2.1 -- # [ scan := scan advanced to the next line, or EOF # L +:= (text up to end of line in scan) + "\n" ] endp: None scan: @, advanced to next line L: @+(text from scan through end of line)+"\n" #-- 3 -- if scan.atEndFile: return 1 else: return 0 endp: None scan: @, advanced to next line L: @+(text from scan through end of line)+"\n" return 0 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) -> if there is an SGML_TAG_OPEN anywhere on the current line of scan -> ... else if line in scan is last in file -> ... else -> scan := scan advanced to the start of the next line L +:= (text up to end of line) + "\n" return 0 ] # - - - B o d y . _ _ g r o p e T a g - - - #### Case 1: scan starts with a valid closing tag of type gi #-- 1 -- # [ if scan starts with a valid SGML tag -> # scan := scan advanced past that tag # tag := an SGMLTag object representing that tag # else ... ] scan: @, advanced past initial tag tag: an SGMLTag object representing the initial tag from @(scan) #-- 2 -- # [ if tag is None -> ... # else if tag is a closing tag of type gi -> # return 1 # else -> ... ] scan: @, advanced past initial tag tag: an SGMLTag object representing the initial tag from @(scan) return 1 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) and (gi is a lowercased SGML tag name) and (scan starts with SGML_TAG_OPEN) -> if scan starts with a valid closing tag of type gi -> scan := scan advanced past that tag return 1 else ... ] # - - - B o d y . _ _ g r o p e T a g - - - #### Case 2: scan starts with a badly formed tag #-- 1 -- # [ if scan starts with a valid SGML tag -> # scan := scan advanced past that tag # tag := an SGMLTag object representing that tag # else if scan looks like a tag but it's badly formed -> # scan := scan advanced past the tag or to EOF # Log() +:= error message(s) # tag := None ] tag: None scan: @, advanced past the tag or to EOF Log(): @+(error(s)) #-- 2 -- # [ if tag is None -> # return 1 # else ... ] tag: None scan: @, advanced past the tag or to EOF Log(): @+(error(s)) return 1 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) and (gi is a lowercased SGML tag name) and (scan starts with SGML_TAG_OPEN) -> if scan starts with a valid closing tag of type gi -> ... else if scan starts with a badly formed tag -> scan := scan advanced past that tag or to EOF Log() +:= error message(s) return 1 else -> ... ] # - - - B o d y . _ _ g r o p e T a g - - - #### Case 3: scan starts with a valid tag but not a closing gi tag #-- 1 -- # [ if scan starts with a valid SGML tag -> # scan := scan advanced past that tag # tag := an SGMLTag object representing that tag # else if scan looks like a tag but it's badly formed -> ... ] tag: an SGMLTag object representing the leading tag from @(scan) scan: @, advanced past its leading tag #-- 2 -- # [ if tag is None -> ... # else if tag is a closing tag of type gi -> ... # else -> # L +:= text of tag, or equivalent # return 0 ] tag: an SGMLTag object representing the leading tag from @(scan) scan: @, advanced past its leading tag L: @+(text equivalent of leading tag from @(scan)) return 0 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) and (gi is a lowercased SGML tag name) and (scan starts with SGML_TAG_OPEN) -> if scan starts with a valid closing tag of type gi -> ... else if scan starts with a badly formed tag -> ... else -> scan := scan advanced past the end of the tag L +:= text of the tag, or equivalent return 0 ] # - - - B o d y . _ _ m a k e L i n k - - - #-- OK by inspection