home *** CD-ROM | disk | FTP | other *** search
/ PC World 1997 November / PCWorld_1997-11_cd.bin / software / programy / komix / DATA.Z / stregenera.tcl < prev    next >
Text File  |  1996-11-22  |  10KB  |  363 lines

  1. #---------------------------------------------------------------------------
  2. #
  3. #      (c)     Cadre Technologies Inc.    1996
  4. #
  5. #      File:           @(#)stregenera.tcl    /main/hindenburg/2
  6. #      Author:         <generated>
  7. #      Description:
  8. #---------------------------------------------------------------------------
  9. # SccsId = @(#)stregenera.tcl    /main/hindenburg/2   22 Nov 1996 Copyright 1996 Cadre Technologies Inc.
  10.  
  11. # Start user added include file section
  12. # End user added include file section
  13.  
  14. require "regenerato.tcl"
  15.  
  16. # This class is the entry point of the Smalltalk
  17. # regenerator.
  18.  
  19. Class STRegenerator : {Regenerator} {
  20.     constructor
  21.     method destructor
  22.     method regenerate
  23.     method countExclamationMarks
  24.     method isCategoryHeader
  25.     method processCategoryHeader
  26.     method processMethod
  27.     method getLine
  28.     method isCommentLine
  29.     method parseInitialize
  30.     method parseFile
  31.  
  32.     # Current parsing state, one of initial, inCategory, 
  33.     # inMethod, inMethodBody, skippingGeneratedMethod.
  34.     #
  35.     attribute state
  36.  
  37.     # Indicates whether the last line that was read
  38.     # started in a single quote delimited string.
  39.     #
  40.     attribute startInSingleQuote
  41.  
  42.     # Indicates whether the last line that was read 
  43.     # ended in a single quote delimited string.
  44.     #
  45.     attribute endInSingleQuote
  46.  
  47.     # Indicates whether the last line that was read
  48.     # started in a double quote delimited string.
  49.     #
  50.     attribute startInDoubleQuote
  51.  
  52.     # Indicates whether the last line that was read
  53.     # ended in a double quote delimited string.
  54.     #
  55.     attribute endInDoubleQuote
  56.  
  57.     # Name of the class currently in regeneration.
  58.     #
  59.     attribute currentClassName
  60.  
  61.     # Name of the class implementation
  62.     # currently in regeneration.
  63.     #
  64.     attribute currentClassImplementation
  65.  
  66.     # Category Type currently in regeneration:
  67.     # Class or Instance.
  68.     #
  69.     attribute currentCategoryType
  70. }
  71.  
  72. constructor STRegenerator {class this} {
  73.     set this [Regenerator::constructor $class $this]
  74.     # Start constructor user section
  75.     # End constructor user section
  76.     return $this
  77. }
  78.  
  79. method STRegenerator::destructor {this} {
  80.     # Start destructor user section
  81.     # End destructor user section
  82.     $this Regenerator::destructor
  83. }
  84.  
  85.  
  86. # Regeneration entry point.
  87. #
  88. method STRegenerator::regenerate {this class fileObject} {
  89.     set fileHandler [STFileHandler new]
  90.     $this fileObject $fileObject
  91.     $this fileDesc [$fileHandler openFile $class [$fileHandler stType]]
  92.     if { [$this fileDesc] != "" } {
  93.     $this parseFile
  94.     $fileHandler closeFile [$this fileDesc]
  95.     }
  96. }
  97.  
  98.  
  99. # Count the exclamation marks in <line>, from right to left.
  100. # Returns 0 when the line ends in a string.
  101. # Stops counting when a character other than <space> or
  102. # ! is encountered. Returns the count and
  103. # strips the found exclamation marks
  104. # from <line>.
  105. #
  106. method STRegenerator::countExclamationMarks {this line} {
  107.     upvar $line l
  108.     if { (![regexp {!} $l]) || [$this endInDoubleQuote] || [$this endInSingleQuote] } {
  109.     return 0
  110.     }
  111.     set l [string trimright $l]
  112.     set index [expr [string length $l]-1]
  113.     set count 0
  114.     while { ($index >= 0) && ([regexp {[! ]} [string index $l $index] ch]) } {
  115.     set index [expr $index-1]
  116.     if { $ch == "!" } {
  117.         set count [expr $count+1]
  118.     }
  119.     }
  120.     set l [string range $l 0 $index]
  121.     return $count
  122. }
  123.  
  124.  
  125. # Returns whether <line> contains a category header.
  126. #
  127. method STRegenerator::isCategoryHeader {this line} {
  128.     if { [string first methodsFor $line] != -1 } {
  129.     return 1
  130.     } 
  131.     return 0
  132. }
  133.  
  134.  
  135. # Processes <line> (which is a category header).
  136. # Sets currentClassName, currentCategoryType
  137. # and currentClassImplementation.
  138. #
  139. method STRegenerator::processCategoryHeader {this line} {
  140.     regsub -all "!" $line "" tokenList
  141.     if { [llength $tokenList] < 3 } { 
  142.     puts "ERROR: bad category header found while regenerating [$this currentClassName]"
  143.     return
  144.     }
  145.     $this currentClassName [lindex $tokenList 0]
  146.     
  147.     if { [lindex $tokenList 1] == "class" } {
  148.     $this currentCategoryType "Class"
  149.     } else {
  150.     $this currentCategoryType "Instance"
  151.     }
  152.  
  153.     $this currentClassImplementation [[$this fileObject] getImplementation [$this currentClassName]]
  154. }
  155.  
  156.  
  157. # Processes the method found with
  158. # header <header>, temporaries <temporaries> and
  159. # body <expression>:
  160. # Determines selector and arguments, gets a
  161. # method implementation, warns if the method
  162. # is obsolete.
  163. # Adds temporaries, removes code before
  164. # user code marker if it exists and the marker itself.
  165. # Adds the user added code as one expression.
  166. #
  167. method STRegenerator::processMethod {this header temporaries expression} {
  168.     set selector ""
  169.     set isArgument 0
  170.     set arguments [List new]
  171.     foreach part $header {
  172.     if { !$isArgument } {
  173.         set selector "$selector$part"
  174.         set isArgument 1
  175.     } else {
  176.         $arguments append $part
  177.         set isArgument 0
  178.     }
  179.     }
  180.  
  181.     # do workaround for - as method name: - as parameter is not allowed in tcl
  182.     if { $selector == "-" } {
  183.     set selector "operator-"
  184.     }
  185.    
  186.     set impl [[$this currentClassImplementation] get[$this currentCategoryType]MethodImplementation $selector ""]
  187.  
  188.     if { $impl == "" } {
  189.     puts "WARNING: method $selector is obsolete"
  190.     set impl [[$this currentClassImplementation] get[$this currentCategoryType]MethodImplementation $selector obsolete]
  191.     # for obsolete methods we need to insert the argument names
  192.     $arguments foreach argument {
  193.         $impl addArgument $argument
  194.     }
  195.     $impl hasUserCodePart 1
  196.     }
  197.  
  198.     # do temporaries
  199.     if { $temporaries != "" } {
  200.     regsub -all {\|} [string trim $temporaries] "" tempList
  201.     foreach temporary $tempList {
  202.         $impl addTemporary $temporary
  203.     }
  204.     }
  205.  
  206.     # delete code before user code marker from expression
  207.     set userMarkerIndex [string first [$globals startUserCodeMarker] $expression]
  208.     if { $userMarkerIndex != -1 } {
  209.     set restIndex [expr $userMarkerIndex+[string length [$globals startUserCodeMarker]]+1]
  210.     set expression [string range $expression $restIndex end]
  211.     }
  212.  
  213.     if { $expression != "" } {
  214.         $impl addExpression $expression
  215.         $impl hasUserCode 1
  216.     }
  217. }
  218.  
  219.  
  220. # Reads <line> from file with descriptor fileDesc,
  221. # returns 0 if end of file.
  222. # Updates the start/end in single/double quote
  223. # attributes based on the contents of
  224. # <line>.
  225. #
  226. method STRegenerator::getLine {this line} {
  227.     upvar $line l
  228.     set l [gets [$this fileDesc]]
  229.     if [eof [$this fileDesc]] {
  230.     return 0
  231.     }
  232.  
  233.     # update count stuff
  234.     $this startInSingleQuote [$this endInDoubleQuote]
  235.     $this startInDoubleQuote [$this endInDoubleQuote]
  236.     # get only the 's and "'s
  237.     regsub -all {[^"']} $l "" newLine
  238.     foreach char [split $newLine {}] {
  239.     if { $char == "\"" } {
  240.         if { ![$this endInSingleQuote] } {
  241.         $this endInDoubleQuote [expr 1-[$this endInDoubleQuote]]
  242.         }
  243.     } else {
  244.         if { ![$this endInDoubleQuote] } {
  245.         $this endInSingleQuote [expr 1-[$this endInSingleQuote]]
  246.         }
  247.     }
  248.     }    
  249.     return 1
  250. }
  251.  
  252.  
  253. # Returns whether <line> is a comment line.
  254. #
  255. method STRegenerator::isCommentLine {this line} {
  256.     if { [$this startInDoubleQuote] || [$this endInDoubleQuote] } {
  257.     return 1
  258.     }
  259.  
  260.     if { [string index [string trim $line] 0] == "\"" } {
  261.     return 1
  262.     }
  263.  
  264.     return 0
  265. }
  266.  
  267.  
  268. # Initializes the parse variables.
  269. #
  270. method STRegenerator::parseInitialize {this} {
  271.     $this startInSingleQuote 0
  272.     $this endInSingleQuote 0
  273.     $this startInDoubleQuote 0
  274.     $this endInDoubleQuote 0
  275.     $this state initial
  276. }
  277.  
  278.  
  279. # This method is the parser. Parses the file
  280. # and adds regenerated method bodies.
  281. #
  282. method STRegenerator::parseFile {this} {
  283.     $this parseInitialize 
  284.  
  285.     set line ""
  286.     while { [$this getLine line] } {
  287.     case [$this state] in {
  288.         {initial} {
  289.         if [$this isCategoryHeader $line] {
  290.             $this processCategoryHeader $line
  291.             $this state inCategory
  292.         }
  293.         }
  294.         {inCategory} {
  295.         if { ([string trim $line] != "" ) && (![$this isCommentLine $line]) } {
  296.             set count [$this countExclamationMarks line]
  297.             if $count {
  298.             $this state initial
  299.             } else {
  300.             $this state inMethod
  301.             set methodHeader $line
  302.             set expression ""
  303.             set temporaries ""
  304.             }
  305.         }
  306.         }
  307.         {inMethod} {
  308.         set count [$this countExclamationMarks line]
  309.         if { [string trim $line] == "\"Generated\"" } {
  310.             $this state skippingGeneratedMethod
  311.             continue
  312.         }
  313.         if { ([string trim $line] != "" ) && (![$this isCommentLine $line]) } {
  314.             if { [string index [string trim $line] 0] == "|" } {
  315.             set temporaries [string trim $line]
  316.             } else {
  317.             set expression $line
  318.             }
  319.  
  320.             $this state inMethodBody
  321.         }
  322.         if $count {
  323.             $this processMethod $methodHeader $temporaries $expression
  324.             if { $count == 1 } {
  325.             $this state inCategory
  326.             } else {
  327.             $this state initial
  328.             }
  329.         }
  330.         }
  331.         {inMethodBody} {
  332.         set count [$this countExclamationMarks line]
  333.         if { $expression != "" } {
  334.             set expression "$expression\n$line"
  335.         } else {
  336.             set expression $line
  337.         }
  338.         if $count {
  339.             $this processMethod $methodHeader $temporaries $expression
  340.             if { $count == 1 } {
  341.             $this state inCategory
  342.             } else {
  343.             $this state initial
  344.             }
  345.         }
  346.         }
  347.         {skippingGeneratedMethod} {
  348.         set count [$this countExclamationMarks line]
  349.         if $count {
  350.             if { $count == 1 } {
  351.             $this state inCategory
  352.             } else {
  353.             $this state initial
  354.             }
  355.         }
  356.         }
  357.     }
  358.     }    
  359. }
  360.  
  361. # Do not delete this line -- regeneration end marker
  362.  
  363.