# - - - T m p l P o o l . _ _ i n i t _ _ - - - (by inspection: the invariant on self.__templateMap is satisfied for an empty dictionary) # - - - T m p l P o o l . _ _ g e t i t e m _ _ - - - #### Case 1: self contains a Template for file eff-name(name) self.__templateMap: @ #-- 1 -- if key is None: fileName = DEFAULT_TEMPLATE else: fileName = key self.__templateMap: @ fileName: eff-name(key) #-- 2 -- # [ if self.templateMap has a key (fileName) -> # return the corresponding value # else -> I ] return @(self.__templateMap)[fileName], which is the template for fileName by the class invariant #-- TARGET -- OK [ if (name is a string or None) -> if self contains a Template for file eff-name(name) -> return that Template else if eff_name(name) names a readable, valid template file -> self := self + a Template object representing that file return that Template object else -> raise IOError ] # - - - T m p l P o o l . _ _ g e t i t e m _ _ - - - #### Case 2: eff-name(key) names a readable, valid template file file.__templateMap: @ #-- 1 -- if key is None: fileName = DEFAULT_TEMPLATE else: fileName = key self.__templateMap: @ fileName: eff-name(key), by definition of eff-name #-- 2 -- # [ if self.templateMap has a key (fileName) -> ... # else -> I ] self.__templateMap: @ fileName: eff-name(key), by definition of eff-name #-- 3 -- # [ if fileName names a readable, valid template file -> # result := a Template object representing that file # else -> ... ] self.__templateMap: @ fileName: eff-name(key), by definition of eff-name result: a Template object representing eff-name(key) #-- 4 -- self.__templateMap[fileName] = result self.__templateMap: @+(entry mapping eff-name(key) |-> a Template object representing eff-name(key)) fileName: eff-name(key), by definition of eff-name result: a Template object representing eff-name(key) #-- 5 -- return result self.__templateMap: @+(entry mapping eff-name(key) |-> a Template object representing eff-name(key)) fileName: eff-name(key), by definition of eff-name result: a Template object representing eff-name(key) return a Template object representing eff-name(key) #-- TARGET -- OK [ if (name is a string or None) -> if self contains a Template for file eff-name(name) -> ... else if eff_name(name) names a readable, valid template file -> self := self + a Template object representing that file return that Template object else -> ... ] # - - - T m p l P o o l . _ _ g e t i t e m _ _ - - - #### Case 3: eff-name(key) is not in self, and key #### doesn't name a readable, valid template file self.__templateMap: @ #-- 1 -- if key is None: fileName = DEFAULT_TEMPLATE else: fileName = key self.__templateMap: @ fileName: eff-name(key) #-- 2 -- # [ if self.templateMap has a key (fileName) -> ... # else -> I ] self.__templateMap: @ fileName: eff-name(key) #-- 3 -- # [ if fileName names a readable, valid template file -> # else -> raise IOError ] raise IOError #-- TARGET -- OK [ if (name is a string or None) -> if self contains a Template for file eff-name(name) -> ... else if eff_name(name) names a readable, valid template file -> ... else -> raise IOError ] # - - - T T o k e n . _ _ i n i t _ _ - - - (virtual constructor; must be replaced by subclass) # - - - T T o k e n . w r i t e L i n k - - - by inspection: fromTopic is a Topic object by precondition; toTarget is a Target object by precondition; and the I/F of Topic.relPath(toTarget) is: [ if toTarget is a Target object -> return the pathname (and optional anchor) which, when used in self's directory, points to the output file of toTarget ] # - - - T T o k e n . w r i t e S t d L i n k - - - (by inspection) # - - - L i t e r a l T o k e n . _ _ i n i t _ _ - - - TToken.__init__ ( self, openCondStack, scan ) self.text: Undefined self.text = text self.text: text #-- TARGET -- OK Generic: [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is a conditional expansion token -> ... else if ifStack is skipping -> I else -> outFile +:= the expansion of self in the context of body ] Specific: .text: [ as passed to the constructor ] # - - - L i t e r a l T o k e n . e x p a n d - - - #### Case 1: ifStack.isSkipping() is true if not ifStack.isSkipping(): outFile.write ( self.text ) (no change) #-- TARGET -- OK Generic: [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is a conditional expansion token -> ... else if ifStack is skipping -> I else -> ... ] # - - - L i t e r a l T o k e n . e x p a n d - - - #### Case 2: ifStack.isSkipping() is false outFile: @ if not ifStack.isSkipping(): outFile.write ( self.text ) outFile: @+self.text #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is a conditional expansion token -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - A u t h o r T o k e n . e x p a n d - - - #### Case 1: ifStack.isSkipping() is true if ( ( not ifStack.isSkipping() ) and ( body.author ) ): outFile.write ( body.author ) (no changes) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is a conditional expansion token -> ... else if ifStack is skipping -> I else -> ... ] # - - - A u t h o r T o k e n . e x p a n d - - - #### Case 2: ifStack.isSkipping() is true; body.author is false if ( ( not ifStack.isSkipping() ) and ( body.author ) ): outFile.write ( body.author ) (no changes) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is a conditional expansion token -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - A u t h o r T o k e n . e x p a n d - - - #### Case 3: ifStack.isSkipping() is true; body.author is true if ( ( not ifStack.isSkipping() ) and ( body.author ) ): outFile.write ( body.author ) outFile: @+body.author #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> raise SyntaxError else if self is a valid conditional expansion token -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - B o d y T o k e n . e x p a n d - - - #### Case 1: ifStack.isSkipping() is true if not ifStack.isSkipping(): body.expand ( outFile ) (no changes) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a conditional expansion token -> ... else if ifStack is skipping -> I else -> ... ] # - - - B o d y T o k e n . e x p a n d - - - #### Case 2: ifStack.isSkipping() is false if not ifStack.isSkipping(): body.expand ( outFile ) outFile: @+(strings from list body.text) Note: Invariant on body.text reads: [ if self is valid -> self's expanded body text as a list of strings else -> None ] #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token -> else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - E l s e T o k e n . _ _ i n i t _ _ - - - #### Case 1: There are no open conditions #-- 1 -- # [ call parent constructor ] (no change) #-- 2 -- # [ if openCondStack is empty -> # raise SyntaxError # else -> I ] raise SyntaxError #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> ... else -> raise SyntaxError ] # - - - E l s e T o k e n . _ _ i n i t _ _ - - - #### Case 2: The top condition on openCondStack has already seen #### an `%else;' #-- 1 -- # [ call parent constructor ] (no changes) #-- 2 -- # [ if openCondStack is empty -> ... # else -> I ] (no changes) #-- 3 -- # [ if the top element of openCondStack has already # seen an "%else;" -> # raise SyntaxError # else -> ... ] raise SyntaxError #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> ... else -> raise SyntaxError ] # - - - E l s e T o k e n . _ _ i n i t _ _ - - - #### Case 3: The top condition on openCondStack has not seen #### an `%else;' #-- 1 -- # [ call parent constructor ] (no changes) #-- 2 -- # [ if openCondStack is empty -> ... # else -> I ] (no changes) #-- 3 -- # [ if the top element of openCondStack has already # seen an "%else;" -> ... # else -> # openCondStack := openCondStack with its top element's # skipping state inverted and the # passage of an "%else;" recorded ] openCondStack: @ with its top element's skipping state inverted and the passage of an `%else;' recorded #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> ... openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - E l s e T o k e n . e x p a n d - - - #### Case 1: ifStack is empty #-- 1 -- # [ if ifStack is empty -> # raise SyntaxError # else -> ... ] raise SyntaxError #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> raise SyntaxError else if self is a valid conditional expansion token in the context of ifStack -> ifStack := ifStack adjusted to account for processing self else if ifStack is skipping -> I else -> outFile +:= the expansion of self in the context of body ] # - - - E l s e T o k e n . e x p a n d - - - #### Case 2: ifStack has a top element and it has seen an `%else;' #-- 1 -- # [ if ifStack is empty -> ... # else if ifStack's top element has seen an else -> # raise SyntaxError # else -> ... ] raise SyntaxError #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> raise SyntaxError else -> ... ] # - - - E l s e T o k e n . e x p a n d - - - #### Case 3: ifStack has a top element and it has not seen an `%else;' #-- 1 -- # [ if ifStack is empty -> # raise SyntaxError # else if ifStack's top element has seen an else -> # raise SyntaxError # else -> # ifStack := ifStack with the top Condition object's skipping # state inverted and marked as having seen an `%else;' ] ifStack: @ with its top Condition object's skipping state inverted and marked as having seen an `%else;' #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ifStack := ifStack adjusted to account for processing self else -> ... ] # - - - E n d i f T o k e n . _ _ i n i t _ _ - - - #### Case 1: openCondStack is empty #-- 1 -- # [ call parent constructor ] (no changes) #-- 2 -- # [ if openCondStack is empty -> ... # raise SyntaxError # else -> ... ] raise SyntaxError #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> ... else -> raise SyntaxError ] # - - - E n d i f T o k e n . _ _ i n i t _ _ - - - #### Case 2: openCondStack has at least one element #-- 1 -- # [ call parent constructor ] (no changes) #-- 2 -- # [ if openCondStack is empty -> ... # else -> # openCondStack := openCondStack with its top element popped ] openCondStack: @ with its top element popped #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - E n d i f T o k e n . e x p a n d - - - #### Case 1: ifStack is empty ifStack.end() raise SyntaxError #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> raise SyntaxError else -> ... ] # - - - E n d i f T o k e n . e x p a n d - - - #### Case 2: ifStack is not empty ifStack.end() ifStack: @ with its top condition popped #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ifStack := ifStack adjusted to account for processing self else -> ... ] # - - - I f N e x t T o k e n . _ _ i n i t _ _ - - - #-- 1 -- # [ call parent constructor ] (no changes) #-- 2 -- # [ openCondStack := openCondStack with a new OpenCond pushed # that records scan.lineNo ] openCondStack: @ with a new OpenCond pushed that records scan.lineNo #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - I f N e x t T o k e n . _ _ i n i t _ _ - - - #-- 1 -- # [ call parent constructor ] (no changes) #-- 2 -- # [ openCondStack := openCondStack with a new OpenCond pushed # that records scan.lineNo ] openCondStack: @ + (a new OpenCond pushed that records scan.lineNo) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - I f N e x t T o k e n . e x p a n d - - - #-- 1 -- # [ if body has an effective next topic -> # skipping := 0 # else -> # skipping := 1 ] skipping: (if body has a next topic -> 0, else -> 1) #-- 2 -- # [ ifStack := ifStack with a new Condition object pushed, # whose skipping attribute is (skipping) ] skipping: 0 ifStack: @+(a new Condition object with skipping=(if body has a next topic -> 0, else -> 1)) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ifStack := ifStack adjusted to account for processing self else -> ... ] # - - - I f P r e v T o k e n . _ _ i n i t _ _ - - - #-- 1 -- # [ call parent constructor ] (no change) #-- 2 -- # [ openCondStack := openCondStack with a new OpenCond pushed # that records scan.lineNo ] openCondStack: @+(a new OpenCond that records scan.lineNo) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - I f P r e v T o k e n . e x p a n d - - - #-- 1 -- # [ if body has an effective previous topic -> # skipping := 0 # else -> # skipping := 1 ] skipping: (if body has a prev topic -> 0, else -> 1) #-- 2 -- # [ ifStack := ifStack with a new Condition object pushed, # whose skipping attribute is (skipping) ] skipping: (if body has a prev topic -> 0, else -> 1) ifStack: @+(a new Condition with skipping=(if body has a prev topic -> 0, else -> 1) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ifStack := ifStack adjusted to account for processing self else -> ... ] # - - - I f S e e T o k e n . _ _ i n i t _ _ - - - #-- 1 -- # [ call parent constructor ] (no change) #-- 2 -- # [ openCondStack := openCondStack with a new OpenCond pushed # that records scan.lineNo ] openCondStack: @+(a new OpenCond that records scan.lineNo) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - I f S e e T o k e n . e x p a n d - - - #-- 1 -- # [ if body has an effective see-also topic -> # skipping := 0 # else -> # skipping := 1 ] skipping: (if body has a see-also -> 0, else -> 1) #-- 2 -- # [ ifStack := ifStack with a new Condition object pushed, # whose skipping attribute is (skipping) ] skipping: (if body has a see-also -> 0, else -> 1) ifStack: @+(a new Condition with skipping=(if body has a see-also -> 0, else -> 1) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ifStack := ifStack adjusted to account for processing self else -> ... ] # - - - N e x t T i t l e T o k e n . _ _ i n i t _ _ - - - (does nothing) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - N e x t T i t l e T o k e n . e x p a n d - - - #### Case 1: ifStack is skipping or body has no next topic # [ if (ifStack is skipping) or (body has no next topic) -> I # else -> # outFile +:= title of body's effective next topic ] (no change) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - N e x t T i t l e T o k e n . e x p a n d - - - #### Case 2: ifStack is not skipping and body has a next topic # [ if (ifStack is skipping) or (body has no next topic) -> I # else -> # outFile +:= title of body's effective next topic ] outFile: @+(title of body's effective next topic) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - N e x t U R L T o k e n . _ _ i n i t _ _ - - - (do nothing) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - N e x t U R L T o k e n . e x p a n d - - - #### Case 1: (ifStack is skipping) or (body has no next topic) # [ if (ifStack is skipping) or (body has no next topic) -> I # else -> # outFile +:= an tag linking from body to body's # next topic ] (no change) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - N e x t U R L T o k e n . e x p a n d - - - #### Case 2: (ifStack is not skipping) and (body has a next topic) # [ if (ifStack is skipping) or (body has no next topic) -> I # else -> # outFile +:= an tag linking from body to body's # next topic ] outFile: @+(an tag linking from body to body's next topic) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - P r e v T i t l e T o k e n . _ _ i n i t _ _ - - - (do nothing) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - P r e v T i t l e T o k e n . e x p a n d - - - #### Case 1: (ifStack is skipping) or (body has no previous topic) # [ if (ifStack is skipping) or (body has no previous topic) -> I # else -> ... ] (no change) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - P r e v T i t l e T o k e n . e x p a n d - - - #### Case 2: (ifStack is not skipping) and (body has a previous topic) # [ if (ifStack is skipping) or (body has no previous topic) -> I # else -> # outFile +:= title of body's effective previous topic ] outFile: @+(title of body's effective previous topic) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - P r e v U R L T o k e n . _ _ i n i t _ _ - - - (no change) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - P r e v U R L T o k e n . e x p a n d - - - #### Case 1: (ifStack is skipping) or (body has no previous topic) # [ if (ifStack is skipping) or (body has no previous topic) -> I # else -> # outFile +:= an tag linking from body to body's # previous topic ] (no change) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - P r e v U R L T o k e n . e x p a n d - - - #### Case 2: (ifStack is not skipping) and (body has a previous topic) # [ if (ifStack is skipping) or (body has no previous topic) -> I # else -> # outFile +:= an tag linking from body to body's # previous topic ] outFile: @+(an tag linking from body to body's previous topic) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - S e e T o k e n . _ _ i n i t _ _ - - - (no changes) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - S e e T o k e n . e x p a n d - - - #### Case 1: ifStack is skipping #-- 1 -- # [ if ifStack is skipping -> # return # else -> I ] (no changes) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - S e e T o k e n . e x p a n d - - - #### Case 2: ifStack is skipping #-- 1 -- # [ if ifStack is skipping -> # return # else -> I ] (no changes) #-- 2 -- prefix = "" prefix: "" #-- 3 -- # [ outFile := outFile + prefix + (a list of ... # constructs, one per element of body.seeList, where each # tag links from body to that element, and each link # text is the title of that element, and the list elements # are separated by "; " ] prefix: "" outFile: @+(a list of ... constructs, one per element of body.seeList, where each tag links from body to that element, and each link text is the title of that element, and the list elements are separated by "; " #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - T i t l e T o k e n . _ _ i n i t _ _ - - - (no changes) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - T i t l e T o k e n . e x p a n d - - - #### Case 1: ifStack is skipping # [ if ifStack is skipping -> I # else -> # outFile +:= body's title ] (no changes) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - T i t l e T o k e n . e x p a n d - - - #### Case 2: ifStack is not skipping # [ if ifStack is skipping -> I # else -> # outFile +:= body's title ] outFile: @+(body's title) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - U R L T o k e n . _ _ i n i t _ _ - - - (no changes) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - U R L T o k e n . e x p a n d - - - #### Case 1: ifStack is skipping # [ if ifStack is skipping -> I # else -> # outFile +:= body's URL ] (no changes) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - U R L T o k e n . e x p a n d - - - #### Case 2: ifStack is not skipping # [ if ifStack is skipping -> I # else -> # outFile +:= body's URL ] outFile: @+(body's URL) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - U p d a t e T o k e n . _ _ i n i t _ _ - - - (no changes) #-- TARGET -- OK [ if (openCondStack is a stack of OpenCond objects representing %if-constructs not yet matched by "%endif;") and (scan is a Scan object) -> if this token is valid in the context of openCondStack -> openCondStack := openCondStack adjusted for the token, with a new OpenCond pushed containing scan.lineNo if the token is an %if-construct else -> ... ] # - - - U p d a t e T o k e n . e x p a n d - - - #### Case 1: (ifStack is skipping) or (body has no update string) # [ if (ifStack is skipping) or (body has no update string) -> I # else -> # outFile +:= body's update string ] (no changes) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> I else -> ... ] # - - - U p d a t e T o k e n . e x p a n d - - - #### Case 2: (ifStack is not skipping) and (body has an update string) # [ if (ifStack is skipping) or (body has no update string) -> I # else -> # outFile +:= body's update string ] outFile: @+(body's update string) #-- TARGET -- OK [ if (ifStack is an IfStack object representing the current nesting of %if-constructs) and (body is a Body object representing the context in which the token is to be expanded) and (outFile is a writeable file handle) -> if self is an invalid conditional expansion token in the context of ifStack -> ... else if self is a valid conditional expansion token in the context of ifStack -> ... else if ifStack is skipping -> ... else -> outFile +:= the expansion of self in the context of body ] # - - - T e m p l a t e . _ _ i n i t _ _ - - - #### Case 1: fileName names a readable, valid template file #-- 1 -- self.fileName = fileName self.__tokenList = [] self.__openCondStack = [] self.__ifStack = IfStack() errCount = Log().count() self.fileName: fileName self.__tokenList: [] self.__openCondStack: [] self.__ifStack: an empty IfStack errCount: @(Log().count()) #-- 2 -- # [ if self.fileName names a readable, valid template file -> # self.__tokenList +:= a sequence of TToken objects # representing the contents of that file # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in that file # else -> ... ] self.fileName: fileName self.__openCondStack: [] NB: If the template is valid, its conditionals must be balanced, hence the net growth in __openCondStack is zero. self.__ifStack: an empty IfStack errCount: @(Log().count()) self.__tokenList: (sequence of TTokens representing fileName) #-- 3 -- if errCount < Log().count(): raise IOError, "The template file was not error-free." self.fileName: fileName self.__openCondStack: [] self.__ifStack: an empty IfStack errCount: @(Log().count()) self.__tokenList: (sequence of TTokens representing fileName) #-- TARGET -- OK [ if fileName is a string -> if fileName names a readable, valid template file -> return a new Template object representing that file else -> ... ] # - - - T e m p l a t e . _ _ i n i t _ _ - - - #### Case 2: fileName doesn't name a readable, valid template file #-- 1 -- self.fileName = fileName self.__tokenList = [] self.__openCondStack = [] self.__ifStack = IfStack() errCount = Log().count() self.fileName: fileName self.__tokenList: [] self.__openCondStack: [] self.__ifStack: an empty IfStack errCount: @(Log().count()) #-- 2 -- # [ if self.fileName names a readable, valid template file -> ... # else -> # self.__tokenList +:= valid TTokens, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in that file # Log() +:= error message(s) ] self.fileName: fileName self.__tokenList: list of valid TTokens, if any self.__openCondStack: [Conditions for unmatched conditionals] self.__ifStack: an empty IfStack errCount: @(Log().count())+(number of errors, at least 1) #-- 3 -- if errCount < Log().count(): raise IOError, "The template file was not error-free." raise IOError #-- TARGET -- OK [ if fileName is a string -> if fileName names a readable, valid template file -> ... else -> Log() +:= error message(s) raise IOError ] # - - - T e m p l a t e . _ _ r e a d F i l e - - - #### Case 1: self.fileName does not name a readable file #-- 1 -- # [ if self.fileName names a readable file -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if self.fileName names a readable, valid template file -> ... else -> self.__tokenList +:= valid TTokens, if any self.__openCondStack := self.__openCondStack adjusted according to valid conditionals in that file Log() +:= error message(s) ] # - - - T e m p l a t e . _ _ r e a d F i l e - - - #### Case 2: self.fileName names a readable, template file that is #### valid except for unclosed conditionals #-- 1 -- # [ if self.fileName names a readable file -> # scan := a new Scan object pointing to the start of that file # else -> ... ] scan: a Scan object pointing to the start of self.fileName #-- 2 -- # [ if scan contains a valid template file -> ... # scan := scan advanced to end of file # self.__tokenList +:= a sequence of TToken objects # representing the contents of scan # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in scan # else -> ... ] scan: advanced to end of file self.__tokenList: @+(valid TTokens from scan, if any self.__openCondStack: @+(Conditions for unclosed conditionals in scan) #-- 3 -- # [ if self.__openCondStack is empty -> ... # else -> # Log() +:= error message(s) ] scan: advanced to end of file self.__tokenList: @+(valid TTokens from scan, if any self.__openCondStack: @+(Conditions for unclosed conditionals in scan) Log(): @+(error message(s)) #-- TARGET -- OK [ if self.fileName names a readable, valid template file -> ... else -> self.__tokenList +:= valid TTokens, if any self.__openCondStack := self.__openCondStack adjusted according to valid conditionals in that file Log() +:= error message(s) ] # - - - T e m p l a t e . _ _ r e a d F i l e - - - #### Case 3: self.fileName names a readable template file that is invalid #-- 1 -- # [ if self.fileName names a readable file -> # scan := a new Scan object pointing to the start of that file # else -> ... ] scan: a Scan object pointing to the start of self.fileName #-- 2 -- # [ if scan contains a valid template file -> ... # else -> ... # scan := scan advanced to end of file # self.__tokenList +:= valid TTokens from scan, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in scan # Log() +:= error message(s) ] scan: @ advanced to EOF self.__tokenList: @+(valid TTokens from scan, if any) self.__openCondStack: @+(Conditions for open conditionals, if any) Log(): @+(error message(s)) #-- 3 -- # [ if self.__openCondStack is empty -> I # else -> ... ] scan: @ advanced to EOF self.__tokenList: @+(valid TTokens from scan, if any) self.__openCondStack: @+(Conditions for open conditionals, if any) Log(): @+(error message(s)) #-- TARGET -- OK [ if self.fileName names a readable, valid template file -> ... else -> self.__tokenList +:= valid TTokens, if any self.__openCondStack := self.__openCondStack adjusted according to valid conditionals in that file Log() +:= error message(s) ] # - - - T e m p l a t e . _ _ r e a d F i l e - - - #### While: termination #### Case 1: File is empty -> scan.endFile will be set initially #### Case 2: scan starts with a valid format code -> scan is advanced #### Case 3: scan starts with a bad format code -> scan is advanced at least one #### Case 4: scan does not start with a format code -> scan is advanced to the next format code or EOF #### While: False case -> assume scan.atEndFile is true -> OK self.__tokenList: no change self.__openCondStack: no change #### While: True case #### Case 1: scan starts with a valid format code # [ if scan starts with a valid format code -> # scan := scan advanced past that format code # self.__tokenList +:= a TToken object representing # that code # else -> ... ] scan: scan advanced past that format code self.__tokenList: @+(a TToken object representing that code) # [ if scan contains a valid template file -> # scan := scan advanced to end of file # self.__tokenList +:= a sequence of TToken objects # representing the contents of scan # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in scan # else -> # scan := scan advanced to end of file # self.__tokenList +:= valid TTokens from scan, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in scan # Log() +:= error message(s) ] scan: scan advanced to end of file self.__tokenList: @+(a TToken object representing that code)+(sequence of TToken objects representing the contents of scan) self.__openCondStack: @ adjusted for that code if necessary, then adjusted for contents of scan #-- TARGET -- OK # [ if scan contains a valid template file -> # scan := scan advanced to end of file # self.__tokenList +:= a sequence of TToken objects # representing the contents of scan # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in scan # else -> # scan := scan advanced to end of file # self.__tokenList +:= valid TTokens from scan, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in scan # Log() +:= error message(s) ] #### Case 2: scan starts with a bad format code # [ if scan starts with a valid format code -> ... # else if scan starts with a bad format code -> # scan := scan advanced the valid part, at least one # Log() +:= error message # else -> ... ] scan: @ advanced past valid part, at least one Log(): @+(error message) # [ if scan contains a valid template file -> # scan := scan advanced to end of file # self.__tokenList +:= a sequence of TToken objects # representing the contents of scan # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in scan # else -> # scan := scan advanced to end of file # self.__tokenList +:= valid TTokens from scan, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in scan # Log() +:= error message(s) ] scan: @ advanced to EOF Log(): @+(error message)+(errors from scan, if any) self.__tokenList: @+(TTokens from scan) self.__openCondStack: @, adjusted from scan #-- TARGET -- OK # [ if scan contains a valid template file -> # scan := scan advanced to end of file # self.__tokenList +:= a sequence of TToken objects # representing the contents of scan # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in scan # else -> # scan := scan advanced to end of file # self.__tokenList +:= valid TTokens from scan, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in scan # Log() +:= error message(s) ] #### Case 3: scan does not start with a format code # [ if scan starts with a valid format code -> ... # else if scan starts with a bad format code -> ... # else -> # scan := scan advanced up to the next format code or EOF # self.__tokenList +:= a TToken representing all text # up to the next format code or EOF ] scan: @ advanced to next format code or EOF self.__tokenList: @+(literal token for text up to next format code or EOF) # [ if scan contains a valid template file -> # scan := scan advanced to end of file # self.__tokenList +:= a sequence of TToken objects # representing the contents of scan # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in scan # else -> # scan := scan advanced to end of file # self.__tokenList +:= valid TTokens from scan, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in scan # Log() +:= error message(s) ] scan: @ advanced to EOF self.__tokenList: @+(literal token for text up to next format code or EOF)+ (tokens from scan) self.__openCondStack: @ adjusted according to scan Log(): @+(errors from scan, if any) #-- TARGET -- OK # [ if scan contains a valid template file -> # scan := scan advanced to end of file # self.__tokenList +:= a sequence of TToken objects # representing the contents of scan # self.__openCondStack := self.__openCondStack adjusted # according to conditionals in scan # else -> # scan := scan advanced to end of file # self.__tokenList +:= valid TTokens from scan, if any # self.__openCondStack := self.__openCondStack adjusted # according to valid conditionals in scan # Log() +:= error message(s) ] # - - - T e m p l a t e . _ _ r e a d T o k e n - - - #### Case 1: scan starts with START_FORMAT not followed by a valid #### format code #-- 1 -- # [ if scan starts with a START_FORMAT not followed by a valid # format code -> # scan := scan advanced past the START_FORMAT and any # following valid part # Log() +:= error message # else if scan starts with a valid format code -> ... # else -> ... ] scan: @ advanced past the START_FORMAT and any following valid part Log(): @+(error message) #-- TARGET -- OK [ if scan starts with a valid format code -> ... else if scan starts with a bad format code -> scan := scan advanced the valid part, at least one Log() +:= error message else -> ... ] # - - - T e m p l a t e . _ _ r e a d T o k e n - - - #### Case 2: scan starts with a valid format code #-- 1 -- # [ if scan starts with a START_FORMAT not followed by a valid # format code -> ... # else if scan starts with a valid format code -> # scan := scan advanced past the format code # self.__tokenList +:= a TToken representing the format code # self.__openCondStack := self.__openCondStack adjusted # for that code, if necessary # else -> ... ] scan: @ advanced past the leading format code self.__tokenList: @+(a TToken representing that format code) self.__openCondStack: @, adjusted for the format code if necessary #-- TARGET -- OK [ if scan starts with a valid format code -> scan := scan advanced past that format code self.__tokenList +:= a TToken object representing that code self.__openCondStack := self.__openCondStack adjusted for that code, if necessary else if scan starts with a bad format code -> ... else -> ... ] # - - - T e m p l a t e . _ _ r e a d T o k e n - - - #### Case 3: scan does not start with a format code #-- 1 -- # [ if scan starts with a START_FORMAT not followed by a valid # format code -> ... # else if scan starts with a valid format code -> ... # else -> # scan := scan advanced up to the next format code or EOF # self.__tokenList +:= a TToken representing all text # up to the next format code or EOF ] scan: @, advanced up to the next format code or EOF self.__tokenList: @+(a TToken repr. all text up to next format code or EOF) #-- TARGET -- OK [ if scan starts with a valid format code -> ... else if scan starts with a bad format code -> ... else -> scan := scan advanced up to the next format code self.__tokenList +:= a TToken representing all text up to the next format code or EOF ] # - - - T e m p l a t e . _ _ r e a d T o k e n - - - #### 1 vs 1.1/1.2: Case 1, scan starts with a START_FORMAT #### followed by a valid format code if scan.tabMatch ( START_FORMAT ): scan: @, advanced past START_FORMAT #-- 1.1 -- # [ if scan starts with a valid format code name followed by # END_FORMAT -> # scan := scan advanced past all that # self.__tokenList +:= a TToken representing that # format code # self.__openCondStack := self.__openCondStack adjusted # for that code, if necessary # else -> ... ] scan: @, advanced past START_FORMAT, format code name, and END_FORMAT self.__tokenList: @+(a TToken representing that format code) self.__openCondStack: @, adjusted for that format code if necessary #-- TARGET -- OK #-- 1 -- # [ if scan starts with a START_FORMAT not followed by a valid # format code -> ... # else if scan starts with a valid format code -> # scan := scan advanced past the format code # self.__tokenList +:= a TToken representing the format code # self.__openCondStack := self.__openCondStack adjusted # for that code, if necessary # else -> ... ] # - - - T e m p l a t e . _ _ r e a d T o k e n - - - #### 1 vs 1.1/1.2: Case 2, scan starts with a START_FORMAT *not* #### followed by a valid format code if scan.tabMatch ( START_FORMAT ): scan: @, advanced past START_FORMAT #-- 1.1 -- # [ if scan starts with a valid format code name followed by # END_FORMAT -> ... # else -> # scan := scan advanced past any leading characters # in FORMAT_NAME_CSET, then END_FORMAT if present # Log() +:= error message ] scan: @, advanced past START_FORMAT and any leading characters in FORMAT_NAME_CSET and END_FORMAT if present Log: @+(error message) #-- TARGET -- OK #-- 1 -- # [ if scan starts with a START_FORMAT not followed by a valid # format code -> # scan := scan advanced past the START_FORMAT and any # following valid part # Log() +:= error message # else if scan starts with a valid format code -> ... # else -> ... ] # - - - T e m p l a t e . _ _ r e a d T o k e n - - - #### 1 vs 1.1/1.2: Case 3, scan doesn't start with START_FORMAT if scan.tabMatch ( START_FORMAT ): scan: @ #-- 1.2 -- # [ scan := scan advanced up to the next # START_FORMAT or EOF # self.__tokenList +:= a literal TToken containing all # characters from scan up to the # next START_FORMAT or EOF ] scan: @, advanced to the next START_FORMAT or EOF self.__tokenList: @+(a literal TToken containing all characters from scan up to the next START_FORMAT or EOF #-- TARGET -- OK #-- 1 -- # [ if scan starts with a START_FORMAT not followed by a valid # format code -> ... # else if scan starts with a valid format code -> ... # else -> # scan := scan advanced up to the next format code or EOF # self.__tokenList +:= a TToken representing all text # up to the next format code or EOF ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l - - - #### Case 1: At least one START_FORMAT remains in scan #-- 1 -- L = [] L: [] #-- 2 -- # [ if at least one START_FORMAT remains in scan -> # scan := scan advanced up to the first START_FORMAT # L +:= text up to the first START_FORMAT as a sequence # of strings # else -> ... ] scan: @, advanced up to the first START_FORMAT L: text up to the first START_FORMAT in scan, as a sequence of strings #-- 3 -- # [ self.__tokenList := a LiteralToken representing the # concatenation of the strings in L ] scan: @, advanced up to the first START_FORMAT L: text up to the first START_FORMAT in scan, as a sequence of strings self.__tokenList: @+(a LiteralToken representing the text up to the first START_FORMAT in scan) #-- TARGET -- OK [ scan := scan advanced up to the next START_FORMAT or EOF self.__tokenList +:= characters from scan up to the next START_FORMAT or EOF ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l - - - #### Case 2: No START_FORMAT remains in scan #-- 1 -- L = [] L: [] #-- 2 -- # [ if at least one START_FORMAT remains in scan -> ... # else -> # scan := scan advanced to EOF # L +:= text remaining in scan as a sequence of strings ] scan: @, advanced to EOF L: text from @(scan) to EOF as a sequence of strings #-- 3 -- # [ self.__tokenList := a LiteralToken representing the # concatenation of the strings in L ] scan: @, advanced to EOF L: text from @(scan) to EOF as a sequence of strings self.__tokenList: @+(a LiteralToken representing all text from @(scan) to EOF) #-- TARGET -- OK [ scan := scan advanced up to the next START_FORMAT or EOF self.__tokenList +:= characters from scan up to the next START_FORMAT or EOF ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l - - - #### While, case 1: line in scan contains a START_FORMAT done = 0 done: 0 #-- 2 body -- # [ if line in scan contains a START_FORMAT -> # scan := scan advanced up to the first START_FORMAT # L +:= text from scan up to the first START_FORMAT # done := 1 # else if line in scan is the last in the file -> ... # else -> ... ] done: 1 scan: @, advanced up to the first START_FORMAT L: @+(text from scan up to the first START_FORMAT) #-- TARGET -- OK # [ if at least one START_FORMAT remains in scan -> # scan := scan advanced up to the first START_FORMAT # L +:= text up to the first START_FORMAT in scan, # as a sequence of strings # else -> ... ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l - - - #### While, case 2: line in scan does not contain a START_FORMAT #### and line in scan is last in file done = 0 done: 0 #-- 2 body -- # [ if line in scan contains a START_FORMAT -> ... # else if line in scan is the last in the file -> # scan := scan advanced to EOF # L +:= remaining text in scan # done := 1 # else -> ... ] done: 1 scan: @, advanced to EOF L: @+(remaining text from scan) #-- TARGET -- OK # [ if at least one START_FORMAT remains in scan -> ... # else -> # scan := scan advanced to EOF # L +:= text remaining in scan as a sequence of strings ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l - - - #### While, case 3: line in scan does not contain a START_FORMAT, #### line in scan is not last in file, and file contains no more START_FORMAT done = 0 done: 0 #-- 2 body -- # [ if line in scan contains a START_FORMAT -> ... # else if line in scan is the last in the file -> ... # else -> # scan := scan advanced to the next line # L +:= (remaining text on line in scan) + "\n" # done := 0 ] done: 0 scan: @, advanced to next line L: @+(remaining text from line in scan+"\n") #-- 2 -- # [ if at least one START_FORMAT remains in scan -> ... # else -> # scan := scan advanced to EOF # L +:= text remaining in scan as a sequence of strings # done := 1 ] done: 1 scan: @, advanced to EOF L: @+(remaining text from line in scan+"\n"+text remaining in scan) #-- TARGET -- OK #-- 2 -- # [ if at least one START_FORMAT remains in scan -> ... # else -> # scan := scan advanced to EOF # L +:= text remaining in scan as a sequence of strings ] # done := 1 ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l - - - #### While, case 4: line in scan does not contain a START_FORMAT, #### line in scan is not last in file, and file contains another START_FORMAT done = 0 done: 0 #-- 2 body -- # [ if line in scan contains a START_FORMAT -> ... # else if line in scan is the last in the file -> ... # else -> # scan := scan advanced to the next line # L +:= (remaining text on line in scan) + "\n" # done := 0 ] done: 0 scan: @, advanced to next line L: @+(remaining text from line in scan+"\n") #-- 2 -- # [ if at least one START_FORMAT remains in scan -> # scan := scan advanced up to the first START_FORMAT # L +:= text up to the first START_FORMAT in scan, # as a sequence of strings # done := 1 # else -> ... ] done: 1 scan: @, advance to first START_FORMAT L: @+(remaining text from line in scan+"\n"+text up to first START_FORMAT in scan) #-- TARGET -- OK #-- 2 -- # [ if at least one START_FORMAT remains in scan -> # scan := scan advanced up to the first START_FORMAT # L +:= text up to the first START_FORMAT in scan, # as a sequence of strings # done := 1 # else -> # scan := scan advanced to EOF # L +:= text remaining in scan as a sequence of strings ] # done := 1 ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l L i n e - - - #### Case 1: line in scan contains a START_FORMAT #-- 1 -- # [ if line in scan contains a START_FORMAT -> # endp := position of the first such # else -> ... ] endp: position of the first START_FORMAT in scan's line #-- 2 -- # [ if endp is None -> ... # else -> # scan := endp # L +:= text from scan up to endp # return 1 ] scan: position of the first START_FORMAT past @ L: @+(text from @(scan) up to endp) return 1 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) -> if line in scan contains a START_FORMAT -> scan := scan advanced up to the first START_FORMAT L +:= text from scan up to the first START_FORMAT return 1 else if line in scan is the last in the file -> ... else -> ... ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l L i n e - - - #### Case 2: line in scan contains no START_FORMAT and is last line #-- 1 -- # [ if line in scan contains a START_FORMAT -> # endp := position of the first such # else -> # endp := None ] endp: None #-- 2 -- # [ if endp is None -> # scan := scan advanced to the next line # L +:= (remainder of line in scan) + "\n" # else -> ... ] scan: @, advanced to EOF L: @+(remainder of line in scan) #-- 3 -- if scan.atEndFile: return 1 else: return 0 scan: @, advanced to EOF L: @+(remainder of line in scan) return 1 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) -> if line in scan contains a START_FORMAT -> ... else if line in scan is the last in the file -> scan := scan advanced to EOF L +:= remaining text in scan return 1 else -> ... ] # - - - T e m p l a t e . _ _ r e a d L i t e r a l L i n e - - - #### Case 3: line in scan contains no START_FORMAT and is not last line #-- 1 -- # [ if line in scan contains a START_FORMAT -> # endp := position of the first such # else -> # endp := None ] endp: None #-- 2 -- # [ if endp is None -> # scan := scan advanced to the next line # L +:= (remainder of line in scan) + "\n" # else -> ... ] endp: None scan: @, advanced to next line L: @+(remainder of line in scan+"\n") #-- 3 -- if scan.atEndFile: return 1 else: return 0 endp: None scan: @, advanced to next line L: @+(remainder of line in scan+"\n") return 0 #-- TARGET -- OK [ if (scan is a Scan object) and (L is a list) -> if line in scan contains a START_FORMAT -> ... else if line in scan is the last in the file -> ... else -> scan := scan advanced to the next line L +:= (remaining text on line in scan) + "\n" return 0 ] # - - - T e m p l a t e . _ _ r e a d F o r m a t - - - #### Case 1: scan starts with START_FORMAT (doubled %% case) #-- 1 -- # [ if scan starts with START_FORMAT -> # scan := scan advanced one # self.__tokenList +:= a LiteralToken containing "%" # return # else -> I ] if scan.tabMatch ( START_FORMAT ): self.__tokenList.append ( LiteralToken ( START_FORMAT ) ) return scan: @, advanced one self.__tokenList: @+(a LiteralToken containing START_FORMAT) return #-- TARGET -- OK [ if (scan is a Scan object) -> if scan starts with START_FORMAT -> scan := scan advanced one self.__tokenList +:= a literal TToken containing START_FORMAT eles if scan starts with a valid format code name followed by END_FORMAT -> ... else -> ... ] # - - - T e m p l a t e . _ _ r e a d F o r m a t - - - #### Case 2: scan starts with a character not in FORMAT_NAME_CSET #-- 1 -- # [ if scan starts with START_FORMAT -> ... # else -> I ] I #-- 2 -- # [ if scan starts with a character in FORMAT_NAME_CSET -> ... # else -> # Log() +:= error message # return ] Log(): @+(error message) return #-- TARGET -- OK [ if (scan is a Scan object) -> if scan starts with START_FORMAT -> ... else if scan starts with a valid format code name followed by END_FORMAT -> ... else -> scan := scan advanced past any leading characters in FORMAT_NAME_CSET, then END_FORMAT if present Log() +:= error message ] # - - - T e m p l a t e . _ _ r e a d F o r m a t - - - #### Case 3: scan starts with one or more characters in FORMAT_NAME_CSET #### but they are not followed by END_FORMAT #-- 1 -- # [ if scan starts with START_FORMAT -> ... # else -> I ] I #-- 2 -- # [ if scan starts with a character in FORMAT_NAME_CSET -> # scan := scan advanced past all leading characters in # FORMAT_NAME_CSET # gi := those characters, lowercased (NB: `gi' stands # for `generic identifier,' which is the standard term for # the name of an SGML tag) # else -> ... ] scan: @, advanced past all leading characters in FORMAT_NAME_CSET gi: all leading characters in FORMAT_NAME_CSET from scan #-- 3 -- # [ if scan starts with END_FORMAT -> ... # else -> # Log() +:= error message # return ] scan: @, advanced past all leading characters in FORMAT_NAME_CSET gi: all leading characters in FORMAT_NAME_CSET from scan Log(): @+(error message) return #-- TARGET -- OK [ if (scan is a Scan object) -> if scan starts with START_FORMAT -> ... else if scan starts with a valid format code name followed by END_FORMAT -> ... else -> scan := scan advanced past any leading characters in FORMAT_NAME_CSET, then END_FORMAT if present Log() +:= error message ] # - - - T e m p l a t e . _ _ r e a d F o r m a t - - - #### Case 4: scan starts with a string that is a key NOT in `formatScanners' #### followed by END_FORMAT #-- 1 -- # [ if scan starts with START_FORMAT -> ... # else -> I ] I #-- 2 -- # [ if scan starts with a character in FORMAT_NAME_CSET -> # scan := scan advanced past all leading characters in # FORMAT_NAME_CSET # gi := those characters, lowercased (NB: `gi' stands # for `generic identifier,' which is the standard term for # the name of an SGML tag) # else -> # Log() +:= error message # return ] scan: scan advanced past all leading characters in FORMAT_NAME_CSET gi: all leading characters from scan in FORMAT_NAME_CSET #-- 3 -- # [ if scan starts with END_FORMAT -> # scan := scan advanced one # else -> # Log() +:= error message # return ] scan: scan advanced past all leading characters in FORMAT_NAME_CSET and then past END_FORMAT gi: all leading characters from scan in FORMAT_NAME_CSET #-- 4 -- # [ if gi is a key in self.formatScanners) # and (the corresponding value can be used as a constructor # in the context of self.__openCondStack and scan) -> ... # else -> # Log() +:= error message ] scan: scan advanced past all leading characters in FORMAT_NAME_CSET and then past END_FORMAT gi: all leading characters from scan in FORMAT_NAME_CSET Log(): @+(error message) #-- TARGET -- OK [ if (scan is a Scan object) -> if scan starts with START_FORMAT -> ... else if scan starts with a valid format code name followed by END_FORMAT -> ... else -> scan := scan advanced past any leading characters in FORMAT_NAME_CSET, then END_FORMAT if present Log() +:= error message ] # - - - T e m p l a t e . _ _ r e a d F o r m a t - - - #### Case 5: scan starts with a string that IS a key in `formatScanners' #### followed by END_FORMAT #-- 1 -- # [ if scan starts with START_FORMAT -> # scan := scan advanced one # self.__tokenList +:= a LiteralToken containing START_FORMAT # return # else -> I ] I #-- 2 -- # [ if scan starts with a character in FORMAT_NAME_CSET -> # scan := scan advanced past all leading characters in # FORMAT_NAME_CSET # gi := those characters, lowercased (NB: `gi' stands # for `generic identifier,' which is the standard term for # the name of an SGML tag) # else -> # Log() +:= error message # return ] scan: @, advanced past all leading characters in FORMAT_NAME_CSET gi: all leading characters from scan in FORMAT_NAME_CSET, lowercased #-- 3 -- # [ if scan starts with END_FORMAT -> # scan := scan advanced one # else -> # Log() +:= error message # return ] scan: @, advanced past all leading characters in FORMAT_NAME_CSET and then one more gi: all leading characters from scan in FORMAT_NAME_CSET, lowercased #-- 4 -- # [ if gi is a key in self.formatScanners) # and (the corresponding value can be used as a constructor # in the context of self.__openCondStack and scan) -> # self.__tokenList +:= an object so constructed # self.__openCondStack := self.__openCondStack adjusted # by that constructor # else -> # Log() +:= error message ] scan: @, advanced past all leading characters in FORMAT_NAME_CSET and then one more gi: all leading characters from scan in FORMAT_NAME_CSET, lowercased self.__tokenList: @+(self.formatScanners[gi] used as a constructor in the context of self.__openCondStack and scan) self.__openCondStack: @, adjusted by (self.formatScanners[gi] used as a constructor in the context of self.__openCondStack and scan) #-- TARGET -- OK [ if (scan is a Scan object) -> if scan starts with START_FORMAT -> ... else if scan starts with a valid format code name followed by END_FORMAT -> scan := scan advanced past all that self.__tokenList +:= a TToken representing that format code self.__openCondStack := self.__openCondStack adjusted for that format code else -> ... ] # - - - O p e n C o n d . _ _ i n i t _ _ - - - (trivial) # - - - O p e n C o n d . e l s e - - - #### Case 1: self.hasElse is 0 if self.hasElse: raise SyntaxError, ( "Only one `%else;' clause is allowed " "to match the `%%%s;' on line %d." % ( self.name, self.lineNo ) ) else: self.hasElse = 1 self.hasElse: 1 #-- TARGET -- OK [ if self.hasElse -> raise SyntaxError else -> self.hasElse := 1 ] # - - - O p e n C o n d . e l s e - - - #### Case 2: self.hasElse is 1 if self.hasElse: raise SyntaxError, ( "Only one `%else;' clause is allowed " "to match the `%%%s;' on line %d." % ( self.name, self.lineNo ) ) else: self.hasElse = 1 raise SyntaxError #-- TARGET -- OK [ if self.hasElse -> raise SyntaxError else -> self.hasElse := 1 ] # - - - I f S t a c k . _ _ i n i t _ _ - - - self.__stack: [] #-- TARGET -- OK .__stack: [ a list of Condition objects, used as a stack with the base at element 0, representing the nested %if-condition constructs at the current point of template expansion ] # - - - I f S t a c k . s t a r t - - - self.__stack.append ( cond ) self.__stack: @+(cond) #-- TARGET -- OK [ if (cond is a Condition object) -> self := self with cond pushed on the stack ] # - - - I f S t a c k . e n d - - - #### Case 1: self.__stack is empty if len ( self.__stack ) === 0: raise SyntaxError, "Mismatched `%end;' conditional" else: ... raise SyntaxError #-- TARGET -- OK [ if self's stack contains at least one element -> ... else -> raise SyntaxError ] # - - - I f S t a c k . e n d - - - #### Case 2: self.__stack is not empty if len ( self.__stack ) == 0: ... else: result = self.__stack[-1] del __stack[-1] return result self.__stack: @-(top) result: top of @(self.__stack) #-- TARGET -- OK [ if self's stack contains at least one element -> self := self with the top condition popped return that condition else -> ... ] # - - - I f S t a c k . e l s e C h e c k - - - #### Case 1: self.__stack is empty if len ( self.__stack ) == 0: #-- 1.1 -- raise SyntaxError, "Mismatched `%else;' conditional" else: ... raise SyntaxError #-- TARGET -- OK [ if self's stack is empty -> raise SyntaxError else if self's top element has seen an else -> ... else -> ... ] # - - - I f S t a c k . e l s e C h e c k - - - #### Case 2: self.__stack's top element has not seen an `%else;' if len ( self.__stack ) == 0: ... else: #-- 1.2 -- # [ if self.__stack has at least one element -> # if top of self.__stack has seen an `%else;' -> ... # else -> # self.__stack := self.__stack with the sense of # its top condition reversed ] self.__stack: @ with sense of top condition reversed #-- TARGET -- [ if self's stack is empty -> ... else if self's top element has seen an else -> ... else -> self := self with the top Condition object's skipping state inverted and marked as having seen an `%else;' ] # - - - I f S t a c k . e l s e C h e c k - - - #### Case 3: self.__stack's top element has seen an `%else;' if len ( self.__stack ) == 0: ... else: #-- 1.2 -- # [ if self.__stack has at least one element -> # if top of self.__stack has seen an `%else;' -> # raise SyntaxError # else -> ... ] raise SyntaxError #-- TARGET -- OK [ if self's stack is empty -> ... else if self's top element has seen an else -> raise SyntaxError else -> ... ] # - - - I f S t a c k . i s S k i p p i n g - - - #### Case 1: self.__stack is empty #-- 1 -- # [ if self.__stack is empty -> # return 0 # else -> I ] return 0 #-- TARGET -- OK [ if self's state implies that we are currently skipping tokens -> return 1 else -> return 0 ] # - - - I f S t a c k . i s S k i p p i n g - - - #### Case 2: self.__stack is not empty and at least one condition #### in self.__stack is skipping #-- 1 -- # [ if self.__stack is empty -> # return 0 # else -> I ] I #-- 2 -- # [ if any of the conditions in self.__stack is skipping -> # return 1 # else -> I ] return 1 #-- TARGET -- OK [ if self's state implies that we are currently skipping tokens -> return 1 else -> return 0 ] # - - - I f S t a c k . i s S k i p p i n g - - - #### Case 3: self.__stack is not empty and none of the conditions #### in self.__stack are skipping #-- 1 -- # [ if self.__stack is empty -> # return 0 # else -> I ] I #-- 2 -- # [ if any of the conditions in self.__stack is skipping -> # return 1 # else -> I ] I #-- 3 -- return 0 return 0 #-- TARGET -- OK [ if self's state implies that we are currently skipping tokens -> return 1 else -> return 0 ] # - - - C o n d i t i o n . _ _ i n i t _ _ - - - self.skipping: skipping self.hasElse: 0 #-- TARGET -- OK .skipping: [ if self is skipping -> 1 else -> 0 ] .hasElse: [ if self has seen an `%else;' -> 1 else -> 0 ] # - - - C o n d i t i o n . _ _ e l s e C h e c k - - - #### Case 1: self.hasElse is 1 if self.hasElse: raise SyntaxError, ( "Only one `%else;' can be used per " "`%if...;' construct." ) else: ... raise SyntaxError #-- TARGET -- OK [ if self has seen an `%else' -> raise SyntaxError else if self.skipping is 1 -> ... else -> ... ] # - - - C o n d i t i o n . _ _ e l s e C h e c k - - - #### Case 2: self.hasElse is 0 and self.skipping is 0 self.hasElse: 0 self.skipping: 0 if self.hasElse: ... else: self.hasElse = 1 if self.skipping: self.skipping = 0 else: self.skipping = 1 self.hasElse: 1 self.skipping: 1 #-- TARGET -- OK [ if self has seen an `%else' -> ... else if self.skipping is 1 -> ... else -> self.skipping := 1 self.hasElse := 1 ] # - - - C o n d i t i o n . _ _ e l s e C h e c k - - - #### Case 3: self.hasElse is 0 and self.skipping is 1 self.hasElse: 0 self.skipping: 1 if self.hasElse: ... else: self.hasElse = 1 if self.skipping: self.skipping = 0 else: self.skipping = 1 self.hasElse: 1 self.skipping: 0 #-- TARGET -- OK [ if self has seen an `%else' -> ... else if self.skipping is 1 -> self.skipping := 0 self.hasElse := 1 else -> ... ]