Scanner.st
changeset 45 e8331ba8ad5d
parent 41 62214c6ca833
child 49 02660b790c3e
equal deleted inserted replaced
44:74ddc944c27f 45:e8331ba8ad5d
     1 "
     1 "
     2  COPYRIGHT (c) 1989 by Claus Gittinger
     2  COPYRIGHT (c) 1989 by Claus Gittinger
     3               All Rights Reserved
     3 	      All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 Object subclass:#Scanner
    13 Object subclass:#Scanner
    14        instanceVariableNames:'source 
    14        instanceVariableNames:'source 
    15                               token tokenType tokenPosition tokenValue
    15 			      token tokenType tokenPosition tokenValue
    16                               tokenName tokenLineNr tokenRadix
    16 			      tokenName tokenLineNr tokenRadix
    17                               thisChar peekChar
    17 			      thisChar peekChar
    18                               requestor exitBlock
    18 			      requestor exitBlock
    19                               errorFlag 
    19 			      errorFlag 
    20                               ignoreErrors ignoreWarnings
    20 			      ignoreErrors ignoreWarnings
    21                               saveComments currentComments
    21 			      saveComments currentComments
    22                               warnSTXSpecialComment
    22 			      warnSTXSpecialComment
    23                               outStream outCol'
    23 			      outStream outCol'
    24           classVariableNames:'TypeArray ActionArray Warnings WarnSTXSpecials'
    24 	  classVariableNames:'TypeArray ActionArray Warnings WarnSTXSpecials'
    25             poolDictionaries:''
    25 	    poolDictionaries:''
    26                     category:'System-Compiler'
    26 		    category:'System-Compiler'
    27 !
    27 !
    28 
    28 
    29 Scanner comment:'
    29 Scanner comment:'
    30 COPYRIGHT (c) 1989 by Claus Gittinger
    30 COPYRIGHT (c) 1989 by Claus Gittinger
    31              All Rights Reserved
    31 	     All Rights Reserved
    32 
    32 
    33 $Header: /cvs/stx/stx/libcomp/Scanner.st,v 1.12 1994-08-23 23:05:01 claus Exp $
    33 $Header: /cvs/stx/stx/libcomp/Scanner.st,v 1.13 1994-10-10 00:57:45 claus Exp $
    34 '!
    34 '!
    35 
    35 
    36 !Scanner class methodsFor:'documentation'!
    36 !Scanner class methodsFor:'documentation'!
    37 
    37 
    38 copyright
    38 copyright
    39 "
    39 "
    40  COPYRIGHT (c) 1989 by Claus Gittinger
    40  COPYRIGHT (c) 1989 by Claus Gittinger
    41               All Rights Reserved
    41 	      All Rights Reserved
    42 
    42 
    43  This software is furnished under a license and may be used
    43  This software is furnished under a license and may be used
    44  only in accordance with the terms of that license and with the
    44  only in accordance with the terms of that license and with the
    45  inclusion of the above copyright notice.   This software may not
    45  inclusion of the above copyright notice.   This software may not
    46  be provided or otherwise made available to, or used by, any
    46  be provided or otherwise made available to, or used by, any
    49 "
    49 "
    50 !
    50 !
    51 
    51 
    52 version
    52 version
    53 "
    53 "
    54 $Header: /cvs/stx/stx/libcomp/Scanner.st,v 1.12 1994-08-23 23:05:01 claus Exp $
    54 $Header: /cvs/stx/stx/libcomp/Scanner.st,v 1.13 1994-10-10 00:57:45 claus Exp $
    55 "
    55 "
    56 !
    56 !
    57 
    57 
    58 documentation
    58 documentation
    59 "
    59 "
    72 !Scanner class methodsFor:'defaults'!
    72 !Scanner class methodsFor:'defaults'!
    73 
    73 
    74 warnings:aBoolean
    74 warnings:aBoolean
    75     "this allows turning on/off warnings; the default is on.
    75     "this allows turning on/off warnings; the default is on.
    76      You can turn off warnings in your 'private.rc' file with
    76      You can turn off warnings in your 'private.rc' file with
    77          Compiler warnings:false
    77 	 Compiler warnings:false
    78     "
    78     "
    79 
    79 
    80     Warnings := aBoolean
    80     Warnings := aBoolean
    81 !
    81 !
    82 
    82 
    83 warnSTXSpecials:aBoolean
    83 warnSTXSpecials:aBoolean
    84     "this allows turning on/off warnings about stx specials.
    84     "this allows turning on/off warnings about stx specials.
    85      If you get bored by those warnings, turn them off by adding
    85      If you get bored by those warnings, turn them off by adding
    86      a line as:
    86      a line as:
    87         Compiler warnSTXSpecials:false
    87 	Compiler warnSTXSpecials:false
    88      in your 'private.rc' file"
    88      in your 'private.rc' file"
    89 
    89 
    90     WarnSTXSpecials := aBoolean
    90     WarnSTXSpecials := aBoolean
    91 ! !
    91 ! !
    92 
    92 
    98     ActionArray := Array new:256.
    98     ActionArray := Array new:256.
    99     TypeArray := Array new:256.
    99     TypeArray := Array new:256.
   100 
   100 
   101     block := [:s :char | s nextNumber].
   101     block := [:s :char | s nextNumber].
   102     ($0 asciiValue) to:($9 asciiValue) do:[:index |
   102     ($0 asciiValue) to:($9 asciiValue) do:[:index |
   103         ActionArray at:index put:block
   103 	ActionArray at:index put:block
   104     ].
   104     ].
   105 
   105 
   106     block := [:s :char | s nextIdentifier].
   106     block := [:s :char | s nextIdentifier].
   107     ($a asciiValue) to:($z asciiValue) do:[:index |
   107     ($a asciiValue) to:($z asciiValue) do:[:index |
   108         ActionArray at:index put:block
   108 	ActionArray at:index put:block
   109     ].
   109     ].
   110     ($A asciiValue) to:($Z asciiValue) do:[:index |
   110     ($A asciiValue) to:($Z asciiValue) do:[:index |
   111         ActionArray at:index put:block
   111 	ActionArray at:index put:block
   112     ].
   112     ].
   113 
   113 
   114     block := [:s :char | s nextSpecial].
   114     block := [:s :char | s nextSpecial].
   115     #( $& $- $+ $= $* $/ $\ $< $> $~ $@ $, $? ) do:[:binop |
   115     #( $& $- $+ $= $* $/ $\ $< $> $~ $@ $, $? ) do:[:binop |
   116         TypeArray at:(binop asciiValue) put:#special.
   116 	TypeArray at:(binop asciiValue) put:#special.
   117         ActionArray at:(binop asciiValue) put:block
   117 	ActionArray at:(binop asciiValue) put:block
   118     ].
   118     ].
   119 
   119 
   120     block := [:s :char | s nextToken:char].
   120     block := [:s :char | s nextToken:char].
   121     #( $; $. $( $) $[ $] $!! $^ $| $_ ) do:[:ch |
   121     #( $; $. $( $) $[ $] $!! $^ $| $_ ) do:[:ch |
   122         ActionArray at:(ch asciiValue) put:block
   122 	ActionArray at:(ch asciiValue) put:block
   123     ].
   123     ].
   124 
   124 
   125     "kludge: action is characterToken, but type is special"
   125     "kludge: action is characterToken, but type is special"
   126     TypeArray at:($| asciiValue) put:#special.
   126     TypeArray at:($| asciiValue) put:#special.
   127 
   127 
   143      if this is the first time, setup character- and action tables"
   143      if this is the first time, setup character- and action tables"
   144 
   144 
   145     errorFlag := false.
   145     errorFlag := false.
   146     tokenLineNr := 1.
   146     tokenLineNr := 1.
   147     aStringOrStream isStream ifFalse:[
   147     aStringOrStream isStream ifFalse:[
   148         source := ReadStream on:aStringOrStream
   148 	source := ReadStream on:aStringOrStream
   149     ] ifTrue:[
   149     ] ifTrue:[
   150         source := aStringOrStream.
   150 	source := aStringOrStream.
   151     ].
   151     ].
   152     currentComments := nil.
   152     currentComments := nil.
   153     saveComments := false.
   153     saveComments := false.
   154     ignoreErrors := false.
   154     ignoreErrors := false.
   155     ignoreWarnings := Warnings not.
   155     ignoreWarnings := Warnings not.
   156     warnSTXSpecialComment := WarnSTXSpecials.
   156     warnSTXSpecialComment := WarnSTXSpecials.
   157 
   157 
   158     ActionArray isNil ifTrue:[
   158     ActionArray isNil ifTrue:[
   159         self class setupActions
   159 	self class setupActions
   160     ]
   160     ]
   161 !
   161 !
   162 
   162 
   163 initialize
   163 initialize
   164     "prepare a scan"
   164     "prepare a scan"
   193 backupPosition
   193 backupPosition
   194     "if reading from a stream, at the end we might have read
   194     "if reading from a stream, at the end we might have read
   195      one token too many"
   195      one token too many"
   196 
   196 
   197     (tokenType == #EOF) ifFalse:[
   197     (tokenType == #EOF) ifFalse:[
   198         source position:tokenPosition
   198 	source position:tokenPosition
   199     ]
   199     ]
   200 !
   200 !
   201 
   201 
   202 beginComment
   202 beginComment
   203     ^ self
   203     ^ self
   204 !
   204 !
   205 
   205 
   206 endComment:comment
   206 endComment:comment
   207     saveComments ifTrue:[
   207     saveComments ifTrue:[
   208         currentComments isNil ifTrue:[
   208 	currentComments isNil ifTrue:[
   209             currentComments := OrderedCollection with:comment
   209 	    currentComments := OrderedCollection with:comment
   210         ] ifFalse:[
   210 	] ifFalse:[
   211             currentComments add:comment
   211 	    currentComments add:comment
   212         ]
   212 	]
   213     ].
   213     ].
   214 ! !
   214 ! !
   215 
   215 
   216 !Scanner methodsFor:'error handling'!
   216 !Scanner methodsFor:'error handling'!
   217 
   217 
   218 showErrorMessage:aMessage position:pos
   218 showErrorMessage:aMessage position:pos
   219     "show an errormessage on the Transcript"
   219     "show an errormessage on the Transcript"
   220 
   220 
   221     ignoreErrors ifFalse:[
   221     ignoreErrors ifFalse:[
   222         Smalltalk silentLoading == true ifFalse:[
   222 	Smalltalk silentLoading == true ifFalse:[
   223             Transcript showCr:(pos printString , ' ' , aMessage)
   223 	    Transcript showCr:(pos printString , ' ' , aMessage)
   224         ]
   224 	]
   225     ]
   225     ]
   226 !
   226 !
   227 
   227 
   228 notifyError:aMessage position:position to:endPos
   228 notifyError:aMessage position:position to:endPos
   229     "notify requestor of an error - if there is no requestor
   229     "notify requestor of an error - if there is no requestor
   230      put it on the transcript.
   230      put it on the transcript.
   231      Return the result passed back by the requestor."
   231      Return the result passed back by the requestor."
   232 
   232 
   233     requestor isNil ifTrue:[
   233     requestor isNil ifTrue:[
   234         self showErrorMessage:aMessage position:position.
   234 	self showErrorMessage:aMessage position:position.
   235         ^ false
   235 	^ false
   236     ].
   236     ].
   237 
   237 
   238     ^ requestor error:aMessage position:position to:endPos
   238     ^ requestor error:aMessage position:position to:endPos
   239 !
   239 !
   240 
   240 
   242     "notify requestor of an warning - if there is no requestor
   242     "notify requestor of an warning - if there is no requestor
   243      put it on the transcript.
   243      put it on the transcript.
   244      Return the result passed back by the requestor."
   244      Return the result passed back by the requestor."
   245 
   245 
   246     requestor isNil ifTrue:[
   246     requestor isNil ifTrue:[
   247         ignoreWarnings ifFalse:[
   247 	ignoreWarnings ifFalse:[
   248             self showErrorMessage:aMessage position:position.
   248 	    self showErrorMessage:aMessage position:position.
   249         ].
   249 	].
   250         ^ false
   250 	^ false
   251     ].
   251     ].
   252     ^ requestor warning:aMessage position:position to:endPos
   252     ^ requestor warning:aMessage position:position to:endPos
   253 !
   253 !
   254 
   254 
   255 syntaxError:aMessage position:position to:endPos
   255 syntaxError:aMessage position:position to:endPos
   313     "
   313     "
   314     self initializeFor:(ReadStream on:aSourceString).
   314     self initializeFor:(ReadStream on:aSourceString).
   315     positions := OrderedCollection new.
   315     positions := OrderedCollection new.
   316 
   316 
   317     [(t := self nextToken) ~~ #EOF] whileTrue:[
   317     [(t := self nextToken) ~~ #EOF] whileTrue:[
   318         searchType == t ifTrue:[
   318 	searchType == t ifTrue:[
   319             (searchName isNil or:[tokenName = searchName]) ifTrue:[
   319 	    (searchName isNil or:[tokenName = searchName]) ifTrue:[
   320                 (searchValue isNil or:[tokenValue = searchValue]) ifTrue:[
   320 		(searchValue isNil or:[tokenValue = searchValue]) ifTrue:[
   321                     positions add:tokenPosition.
   321 		    positions add:tokenPosition.
   322                 ]
   322 		]
   323             ]
   323 	    ]
   324         ]
   324 	]
   325     ].
   325     ].
   326 
   326 
   327     ^ positions
   327     ^ positions
   328 
   328 
   329     "
   329     "
   340 
   340 
   341     comment := ''.
   341     comment := ''.
   342 
   342 
   343     self beginComment.
   343     self beginComment.
   344     outStream notNil ifTrue:[
   344     outStream notNil ifTrue:[
   345         outStream nextPut:Character doubleQuote.
   345 	outStream nextPut:Character doubleQuote.
   346         outCol := outCol + 1
   346 	outCol := outCol + 1
   347     ].
   347     ].
   348 
   348 
   349     startPos := source position.
   349     startPos := source position.
   350     source next.
   350     source next.
   351     thisChar := source peek.
   351     thisChar := source peek.
   356      Since this is non-standard, use it in very rare cases only. 
   356      Since this is non-standard, use it in very rare cases only. 
   357      (maybe the upcoming ansi-standard adds something similar - in this case, I will
   357      (maybe the upcoming ansi-standard adds something similar - in this case, I will
   358       change it without notice)"
   358       change it without notice)"
   359 
   359 
   360     thisChar == $/ ifTrue:[
   360     thisChar == $/ ifTrue:[
   361         [thisChar notNil and:[thisChar ~~ Character cr]] whileTrue:[
   361 	[thisChar notNil and:[thisChar ~~ Character cr]] whileTrue:[
   362             saveComments ifTrue:[
   362 	    saveComments ifTrue:[
   363                 comment := comment copyWith:thisChar
   363 		comment := comment copyWith:thisChar
   364             ].
   364 	    ].
   365             outStream notNil ifTrue:[
   365 	    outStream notNil ifTrue:[
   366                 outStream nextPut:thisChar.
   366 		outStream nextPut:thisChar.
   367                 outCol := outCol + 1
   367 		outCol := outCol + 1
   368             ].
   368 	    ].
   369             thisChar := source nextPeek.
   369 	    thisChar := source nextPeek.
   370         ].
   370 	].
   371         tokenLineNr := tokenLineNr + 1.
   371 	tokenLineNr := tokenLineNr + 1.
   372         ignoreWarnings ifFalse:[
   372 	ignoreWarnings ifFalse:[
   373             warnSTXSpecialComment ifTrue:[
   373 	    warnSTXSpecialComment ifTrue:[
   374                 self warning:'end-of-line comments are a nonstandard feature of ST/X' 
   374 		self warning:'end-of-line comments are a nonstandard feature of ST/X' 
   375                      position:startPos to:(source position).
   375 		     position:startPos to:(source position).
   376                 "
   376 		"
   377                  only warn once
   377 		 only warn once
   378                 "
   378 		"
   379                 warnSTXSpecialComment := false
   379 		warnSTXSpecialComment := false
   380             ]
   380 	    ]
   381         ].
   381 	].
   382         outStream notNil ifTrue:[
   382 	outStream notNil ifTrue:[
   383             outStream cr.
   383 	    outStream cr.
   384             outCol := 1
   384 	    outCol := 1
   385         ].
   385 	].
   386     ] ifFalse:[
   386     ] ifFalse:[
   387         [thisChar notNil and:[thisChar ~~ (Character doubleQuote)]] whileTrue:[
   387 	[thisChar notNil and:[thisChar ~~ (Character doubleQuote)]] whileTrue:[
   388             thisChar == (Character cr) ifTrue:[
   388 	    thisChar == (Character cr) ifTrue:[
   389                 tokenLineNr := tokenLineNr + 1.
   389 		tokenLineNr := tokenLineNr + 1.
   390             ].
   390 	    ].
   391             saveComments ifTrue:[
   391 	    saveComments ifTrue:[
   392                 comment := comment copyWith:thisChar
   392 		comment := comment copyWith:thisChar
   393             ].
   393 	    ].
   394             outStream notNil ifTrue:[
   394 	    outStream notNil ifTrue:[
   395                 outStream nextPut:thisChar.
   395 		outStream nextPut:thisChar.
   396                 outCol := outCol + 1
   396 		outCol := outCol + 1
   397             ].
   397 	    ].
   398             thisChar := source nextPeek
   398 	    thisChar := source nextPeek
   399         ].
   399 	].
   400         thisChar isNil ifTrue:[
   400 	thisChar isNil ifTrue:[
   401             self warning:'unclosed comment' position:startPos to:(source position)
   401 	    self warning:'unclosed comment' position:startPos to:(source position)
   402         ] ifFalse:[
   402 	] ifFalse:[
   403             outStream notNil ifTrue:[
   403 	    outStream notNil ifTrue:[
   404                 outStream nextPut:(Character doubleQuote).
   404 		outStream nextPut:(Character doubleQuote).
   405                 outCol := outCol + 1
   405 		outCol := outCol + 1
   406             ].
   406 	    ].
   407         ]
   407 	]
   408     ].
   408     ].
   409 
   409 
   410     saveComments ifTrue:[
   410     saveComments ifTrue:[
   411         currentComments isNil ifTrue:[
   411 	currentComments isNil ifTrue:[
   412             currentComments := OrderedCollection with:comment
   412 	    currentComments := OrderedCollection with:comment
   413         ] ifFalse:[
   413 	] ifFalse:[
   414             currentComments add:comment
   414 	    currentComments add:comment
   415         ]
   415 	]
   416     ].
   416     ].
   417 
   417 
   418     "skip final dQuote or cr"
   418     "skip final dQuote or cr"
   419     source next.
   419     source next.
   420 
   420 
   425     "return the next token from the source-stream"
   425     "return the next token from the source-stream"
   426 
   426 
   427     |skipping actionBlock|
   427     |skipping actionBlock|
   428 
   428 
   429     peekChar notNil ifTrue:[
   429     peekChar notNil ifTrue:[
   430         thisChar := peekChar.
   430 	thisChar := peekChar.
   431         peekChar := nil
   431 	peekChar := nil
   432     ] ifFalse:[
   432     ] ifFalse:[
   433         skipping := true.
   433 	skipping := true.
   434         [skipping] whileTrue:[
   434 	[skipping] whileTrue:[
   435             outStream notNil ifTrue:[
   435 	    outStream notNil ifTrue:[
   436                 [(thisChar := source peek) == Character space] whileTrue:[
   436 		[(thisChar := source peek) == Character space] whileTrue:[
   437                     source next.
   437 		    source next.
   438                     outStream space. 
   438 		    outStream space. 
   439                     outCol := outCol + 1.
   439 		    outCol := outCol + 1.
   440                 ]
   440 		]
   441             ] ifFalse:[
   441 	    ] ifFalse:[
   442                 thisChar := source skipSeparatorsExceptCR.
   442 		thisChar := source skipSeparatorsExceptCR.
   443             ].
   443 	    ].
   444             thisChar == (Character cr) ifTrue:[
   444 	    thisChar == (Character cr) ifTrue:[
   445                 tokenLineNr := tokenLineNr + 1.
   445 		tokenLineNr := tokenLineNr + 1.
   446                 source next.
   446 		source next.
   447                 outStream notNil ifTrue:[
   447 		outStream notNil ifTrue:[
   448                     outStream cr.
   448 		    outStream cr.
   449                     outCol := 1
   449 		    outCol := 1
   450                 ]
   450 		]
   451             ] ifFalse:[
   451 	    ] ifFalse:[
   452                 thisChar == (Character doubleQuote) ifTrue:[
   452 		thisChar == (Character doubleQuote) ifTrue:[
   453                     "start of a comment"
   453 		    "start of a comment"
   454 
   454 
   455                     self skipComment.
   455 		    self skipComment.
   456                     thisChar := source peek.
   456 		    thisChar := source peek.
   457                 ] ifFalse:[
   457 		] ifFalse:[
   458                     skipping := false
   458 		    skipping := false
   459                 ]
   459 		]
   460             ]
   460 	    ]
   461         ].
   461 	].
   462         thisChar isNil ifTrue:[
   462 	thisChar isNil ifTrue:[
   463             tokenType := #EOF.
   463 	    tokenType := #EOF.
   464             ^ tokenType
   464 	    ^ tokenType
   465         ]
   465 	]
   466     ].
   466     ].
   467     tokenPosition := source position.
   467     tokenPosition := source position.
   468 
   468 
   469     actionBlock := ActionArray at:(thisChar asciiValue).
   469     actionBlock := ActionArray at:(thisChar asciiValue).
   470     actionBlock notNil ifTrue:[
   470     actionBlock notNil ifTrue:[
   471         ^ actionBlock value:self value:thisChar
   471 	^ actionBlock value:self value:thisChar
   472     ].
   472     ].
   473 
   473 
   474     self syntaxError:('invalid character: ''' , thisChar asString , ''' ',
   474     self syntaxError:('invalid character: ''' , thisChar asString , ''' ',
   475                       '(' , thisChar asciiValue printString , ')')
   475 		      '(' , thisChar asciiValue printString , ')')
   476             position:tokenPosition to:tokenPosition.
   476 	    position:tokenPosition to:tokenPosition.
   477     tokenType := #Error.
   477     tokenType := #Error.
   478     ^ #Error
   478     ^ #Error
   479 !
   479 !
   480 
   480 
   481 nextToken:aCharacter
   481 nextToken:aCharacter
   486 
   486 
   487 nextColonOrAssign
   487 nextColonOrAssign
   488     "colon has been read - look for = to make it an assign"
   488     "colon has been read - look for = to make it an assign"
   489 
   489 
   490     (source nextPeek == $=) ifTrue:[
   490     (source nextPeek == $=) ifTrue:[
   491         source next.
   491 	source next.
   492         tokenType := $_
   492 	tokenType := $_
   493     ] ifFalse:[
   493     ] ifFalse:[
   494         tokenType := $:
   494 	tokenType := $:
   495     ].
   495     ].
   496     ^ tokenType
   496     ^ tokenType
   497 !
   497 !
   498     
   498     
   499 nextSpecial
   499 nextSpecial
   503     |firstChar secondChar thirdChar string p|
   503     |firstChar secondChar thirdChar string p|
   504 
   504 
   505     firstChar := source next.
   505     firstChar := source next.
   506     secondChar := source peek.
   506     secondChar := source peek.
   507     (firstChar == $-) ifTrue:[
   507     (firstChar == $-) ifTrue:[
   508         secondChar isDigit ifTrue:[
   508 	secondChar isDigit ifTrue:[
   509             self nextNumber.
   509 	    self nextNumber.
   510             tokenValue := tokenValue negated.
   510 	    tokenValue := tokenValue negated.
   511             ^ tokenType
   511 	    ^ tokenType
   512         ]
   512 	]
   513     ].
   513     ].
   514     string := firstChar asString.
   514     string := firstChar asString.
   515     secondChar notNil ifTrue:[
   515     secondChar notNil ifTrue:[
   516         ((TypeArray at:(secondChar asciiValue)) == #special) ifTrue:[
   516 	((TypeArray at:(secondChar asciiValue)) == #special) ifTrue:[
   517             (secondChar == $-) ifTrue:[
   517 	    (secondChar == $-) ifTrue:[
   518                 "special- look if minus belongs to number following"
   518 		"special- look if minus belongs to number following"
   519                 p := source position.
   519 		p := source position.
   520                 source next.
   520 		source next.
   521                 thirdChar := source peek.
   521 		thirdChar := source peek.
   522                 source position:p.
   522 		source position:p.
   523                 thirdChar isDigit ifTrue:[
   523 		thirdChar isDigit ifTrue:[
   524                     tokenName := string.
   524 		    tokenName := string.
   525                     tokenType := #BinaryOperator.
   525 		    tokenType := #BinaryOperator.
   526                     ^ tokenType
   526 		    ^ tokenType
   527                 ]
   527 		]
   528             ].
   528 	    ].
   529             source next.
   529 	    source next.
   530             string := string copyWith:secondChar
   530 	    string := string copyWith:secondChar
   531         ].
   531 	].
   532     ].
   532     ].
   533     tokenName := string.
   533     tokenName := string.
   534     tokenType := #BinaryOperator.
   534     tokenType := #BinaryOperator.
   535     ^ tokenType
   535     ^ tokenType
   536 !
   536 !
   541     |nextChar|
   541     |nextChar|
   542 
   542 
   543     source next.
   543     source next.
   544     nextChar := source next.
   544     nextChar := source next.
   545     nextChar notNil ifTrue:[
   545     nextChar notNil ifTrue:[
   546         tokenValue := nextChar.
   546 	tokenValue := nextChar.
   547         tokenType := #Character
   547 	tokenType := #Character
   548     ] ifFalse:[
   548     ] ifFalse:[
   549         tokenType := #EOF
   549 	tokenType := #EOF
   550     ].
   550     ].
   551     ^ tokenType
   551     ^ tokenType
   552 !
   552 !
   553 
   553 
   554 nextMantissa:radix
   554 nextMantissa:radix
   556 
   556 
   557     value := 0.
   557     value := 0.
   558     factor := 1.0 / radix.
   558     factor := 1.0 / radix.
   559     nextChar := source peek.
   559     nextChar := source peek.
   560     [(nextChar notNil and:[nextChar isDigitRadix:radix])] whileTrue:[
   560     [(nextChar notNil and:[nextChar isDigitRadix:radix])] whileTrue:[
   561         value := value + (nextChar digitValue * factor).
   561 	value := value + (nextChar digitValue * factor).
   562         factor := factor / radix.
   562 	factor := factor / radix.
   563         nextChar := source nextPeek
   563 	nextChar := source nextPeek
   564     ].
   564     ].
   565     ^ value
   565     ^ value
   566 !
   566 !
   567 
   567 
   568 nextNumber
   568 nextNumber
   570 
   570 
   571     tokenRadix := 10.
   571     tokenRadix := 10.
   572     value := Integer readFrom:source radix:tokenRadix.
   572     value := Integer readFrom:source radix:tokenRadix.
   573     nextChar := source peek.
   573     nextChar := source peek.
   574     (nextChar == $r) ifTrue:[
   574     (nextChar == $r) ifTrue:[
   575         tokenRadix := value.
   575 	tokenRadix := value.
   576         source next.
   576 	source next.
   577         s := 1.
   577 	s := 1.
   578         source peek == $- ifTrue:[
   578 	source peek == $- ifTrue:[
   579             source next.
   579 	    source next.
   580             s := -1
   580 	    s := -1
   581         ].
   581 	].
   582         value := Integer readFrom:source radix:tokenRadix.
   582 	value := Integer readFrom:source radix:tokenRadix.
   583         value := value * s.
   583 	value := value * s.
   584         nextChar := source peek
   584 	nextChar := source peek
   585     ].
   585     ].
   586     (nextChar == $.) ifTrue:[
   586     (nextChar == $.) ifTrue:[
   587         nextChar := source nextPeek.
   587 	nextChar := source nextPeek.
   588         (nextChar notNil and:[nextChar isDigitRadix:tokenRadix]) ifTrue:[
   588 	(nextChar notNil and:[nextChar isDigitRadix:tokenRadix]) ifTrue:[
   589             value := value asFloat + (self nextMantissa:tokenRadix).
   589 	    value := value asFloat + (self nextMantissa:tokenRadix).
   590             nextChar := source peek
   590 	    nextChar := source peek
   591         ] ifFalse:[
   591 	] ifFalse:[
   592             nextChar == (Character cr) ifTrue:[
   592 	    nextChar == (Character cr) ifTrue:[
   593                 tokenLineNr := tokenLineNr + 1.
   593 		tokenLineNr := tokenLineNr + 1.
   594             ].
   594 	    ].
   595             peekChar := $.
   595 	    peekChar := $.
   596         ]
   596 	]
   597     ].
   597     ].
   598     ((nextChar == $e) or:[nextChar == $E]) ifTrue:[
   598     ((nextChar == $e) or:[nextChar == $E]) ifTrue:[
   599         nextChar := source nextPeek.
   599 	nextChar := source nextPeek.
   600         (nextChar notNil and:[(nextChar isDigitRadix:tokenRadix) or:['+-' includes:nextChar]]) ifTrue:[
   600 	(nextChar notNil and:[(nextChar isDigitRadix:tokenRadix) or:['+-' includes:nextChar]]) ifTrue:[
   601             s := 1.
   601 	    s := 1.
   602             (nextChar == $+) ifTrue:[
   602 	    (nextChar == $+) ifTrue:[
   603                 nextChar := source nextPeek
   603 		nextChar := source nextPeek
   604             ] ifFalse:[
   604 	    ] ifFalse:[
   605                 (nextChar == $-) ifTrue:[
   605 		(nextChar == $-) ifTrue:[
   606                     nextChar := source nextPeek.
   606 		    nextChar := source nextPeek.
   607                     s := s negated
   607 		    s := s negated
   608                 ]
   608 		]
   609             ].
   609 	    ].
   610             value := value asFloat
   610 	    value := value asFloat
   611                      * (10.0 raisedToInteger:((Integer readFrom:source radix:tokenRadix) * s))
   611 		     * (10.0 raisedToInteger:((Integer readFrom:source radix:tokenRadix) * s))
   612         ]
   612 	]
   613     ].
   613     ].
   614     tokenValue := value.
   614     tokenValue := value.
   615     (value isMemberOf:Float) ifTrue:[
   615     (value isMemberOf:Float) ifTrue:[
   616         tokenType := #Float
   616 	tokenType := #Float
   617     ] ifFalse:[
   617     ] ifFalse:[
   618         tokenType := #Integer
   618 	tokenType := #Integer
   619     ].
   619     ].
   620     ^ tokenType
   620     ^ tokenType
   621 !
   621 !
   622 
   622 
   623 nextId
   623 nextId
   628     nextChar := source peek.
   628     nextChar := source peek.
   629     string := String new:10.
   629     string := String new:10.
   630     index := 0.
   630     index := 0.
   631     max := 10.
   631     max := 10.
   632     [true] whileTrue:[
   632     [true] whileTrue:[
   633         (nextChar notNil and:[nextChar isAlphaNumeric]) ifFalse:[
   633 	(nextChar notNil and:[nextChar isLetterOrDigit]) ifFalse:[
   634             ^ string copyTo:index
   634 	    ^ string copyTo:index
   635         ].
   635 	].
   636         (index == max) ifTrue:[
   636 	(index == max) ifTrue:[
   637             oldString := string.
   637 	    oldString := string.
   638             string := String new:(max * 2).
   638 	    string := String new:(max * 2).
   639             string replaceFrom:1 to:max with:oldString.
   639 	    string replaceFrom:1 to:max with:oldString.
   640             max := max * 2
   640 	    max := max * 2
   641         ].
   641 	].
   642         index := index + 1.
   642 	index := index + 1.
   643         string at:index put:nextChar.
   643 	string at:index put:nextChar.
   644         nextChar := source nextPeek
   644 	nextChar := source nextPeek
   645     ]
   645     ]
   646 !
   646 !
   647 
   647 
   648 nextIdentifier
   648 nextIdentifier
   649     |nextChar string firstChar|
   649     |nextChar string firstChar|
   650 
   650 
   651     string := source nextWord "self nextId".
   651     string := source nextWord "self nextId".
   652     nextChar := source peek.
   652     nextChar := source peek.
   653     (nextChar == $:) ifTrue:[
   653     (nextChar == $:) ifTrue:[
   654         source next.
   654 	source next.
   655         (source peek == $=) ifFalse:[
   655 	(source peek == $=) ifFalse:[
   656             tokenName := string copyWith:nextChar.
   656 	    tokenName := string copyWith:nextChar.
   657             tokenType := #Keyword.
   657 	    tokenType := #Keyword.
   658             ^ self
   658 	    ^ self
   659         ].
   659 	].
   660         peekChar := $_
   660 	peekChar := $_
   661     ].
   661     ].
   662     tokenName := string.
   662     tokenName := string.
   663     firstChar := string at:1.
   663     firstChar := string at:1.
   664     (firstChar == $s) ifTrue:[
   664     (firstChar == $s) ifTrue:[
   665         (string = 'self') ifTrue:[tokenType := #Self. ^self].
   665 	(string = 'self') ifTrue:[tokenType := #Self. ^self].
   666         (string = 'super') ifTrue:[tokenType := #Super. ^self]
   666 	(string = 'super') ifTrue:[tokenType := #Super. ^self]
   667     ].
   667     ].
   668     (firstChar == $n) ifTrue:[
   668     (firstChar == $n) ifTrue:[
   669         (string = 'nil') ifTrue:[tokenType := #Nil. ^self]
   669 	(string = 'nil') ifTrue:[tokenType := #Nil. ^self]
   670     ].
   670     ].
   671     (firstChar == $t) ifTrue:[
   671     (firstChar == $t) ifTrue:[
   672         (string = 'true') ifTrue:[tokenType := #True. ^self].
   672 	(string = 'true') ifTrue:[tokenType := #True. ^self].
   673         (string = 'thisContext') ifTrue:[tokenType := #ThisContext. ^self]
   673 	(string = 'thisContext') ifTrue:[tokenType := #ThisContext. ^self]
   674     ].
   674     ].
   675     (firstChar == $f) ifTrue:[
   675     (firstChar == $f) ifTrue:[
   676         (string = 'false') ifTrue:[tokenType := #False. ^self]
   676 	(string = 'false') ifTrue:[tokenType := #False. ^self]
   677     ].
   677     ].
   678     tokenType := #Identifier.
   678     tokenType := #Identifier.
   679     ^ tokenType
   679     ^ tokenType
   680 !
   680 !
   681 
   681 
   687     nextChar := source nextPeek.
   687     nextChar := source nextPeek.
   688     string := String new:500.
   688     string := String new:500.
   689     len := 500.
   689     len := 500.
   690     index := 1.
   690     index := 1.
   691     (nextChar == ${) ifTrue:[
   691     (nextChar == ${) ifTrue:[
   692         nextChar := source nextPeek.
   692 	nextChar := source nextPeek.
   693         inPrimitive := true.
   693 	inPrimitive := true.
   694         [inPrimitive] whileTrue:[
   694 	[inPrimitive] whileTrue:[
   695             [nextChar == $%] whileFalse:[
   695 	    [nextChar == $%] whileFalse:[
   696                 string at:index put:nextChar.
   696 		string at:index put:nextChar.
   697                 (index == len) ifTrue:[
   697 		(index == len) ifTrue:[
   698                     string := string , (String new:len).
   698 		    string := string , (String new:len).
   699                     len := len * 2
   699 		    len := len * 2
   700                 ].
   700 		].
   701                 index := index + 1.
   701 		index := index + 1.
   702                 nextChar := source next
   702 		nextChar := source next
   703             ].
   703 	    ].
   704             (source peek == $}) ifTrue:[
   704 	    (source peek == $}) ifTrue:[
   705                 inPrimitive := false
   705 		inPrimitive := false
   706             ] ifFalse:[
   706 	    ] ifFalse:[
   707                 string at:index put:nextChar.
   707 		string at:index put:nextChar.
   708                 (index == len) ifTrue:[
   708 		(index == len) ifTrue:[
   709                     string := string , (String new:len).
   709 		    string := string , (String new:len).
   710                     len := len * 2
   710 		    len := len * 2
   711                 ].
   711 		].
   712                 index := index + 1.
   712 		index := index + 1.
   713                 nextChar := source next
   713 		nextChar := source next
   714             ]
   714 	    ]
   715         ].
   715 	].
   716         source next.
   716 	source next.
   717         tokenValue := string copyTo:(index - 1).
   717 	tokenValue := string copyTo:(index - 1).
   718         tokenType := #Primitive.
   718 	tokenType := #Primitive.
   719         tokenLineNr := tokenLineNr + (tokenValue occurrencesOf:(Character cr)).
   719 	tokenLineNr := tokenLineNr + (tokenValue occurrencesOf:(Character cr)).
   720         ^ tokenType
   720 	^ tokenType
   721     ].
   721     ].
   722 
   722 
   723     "a % alone is a binary operator"
   723     "a % alone is a binary operator"
   724     tokenName := '%'.
   724     tokenName := '%'.
   725     tokenType := #BinaryOperator.
   725     tokenType := #BinaryOperator.
   726     ^ tokenType.
   726     ^ tokenType.
   727 "
   727 "
   728     self syntaxError:('invalid character: ''' , nextChar asString , '''')
   728     self syntaxError:('invalid character: ''' , nextChar asString , '''')
   729             position:tokenPosition to:(tokenPosition + 1).
   729 	    position:tokenPosition to:(tokenPosition + 1).
   730     ^ #Error
   730     ^ #Error
   731 "
   731 "
   732 !
   732 !
   733 
   733 
   734 nextHash
   734 nextHash
   735     |nextChar string|
   735     |nextChar string|
   736 
   736 
   737     nextChar := source nextPeek.
   737     nextChar := source nextPeek.
   738     nextChar notNil ifTrue:[
   738     nextChar notNil ifTrue:[
   739         nextChar isAlphaNumeric ifTrue:[
   739 	nextChar isLetterOrDigit ifTrue:[
   740             string := ''.
   740 	    string := ''.
   741             [nextChar notNil and:[nextChar isAlphaNumeric]] whileTrue:[
   741 	    [nextChar notNil and:[nextChar isLetterOrDigit]] whileTrue:[
   742                 string := string , (source nextWord "self nextId").
   742 		string := string , (source nextWord "self nextId").
   743                 nextChar := source peek.
   743 		nextChar := source peek.
   744                 (nextChar == $:) ifFalse:[
   744 		(nextChar == $:) ifFalse:[
   745                     tokenValue := string asSymbol.
   745 		    tokenValue := string asSymbol.
   746                     tokenType := #Symbol.
   746 		    tokenType := #Symbol.
   747                     ^ tokenType
   747 		    ^ tokenType
   748                 ].
   748 		].
   749                 string := string copyWith:nextChar.
   749 		string := string copyWith:nextChar.
   750                 nextChar := source nextPeek
   750 		nextChar := source nextPeek
   751             ].
   751 	    ].
   752             tokenValue := string asSymbol.
   752 	    tokenValue := string asSymbol.
   753             tokenType := #Symbol.
   753 	    tokenType := #Symbol.
   754             ^ tokenType
   754 	    ^ tokenType
   755         ].
   755 	].
   756         (nextChar == $( ) ifTrue:[
   756 	(nextChar == $( ) ifTrue:[
   757             source next.
   757 	    source next.
   758             tokenType := #HashLeftParen.
   758 	    tokenType := #HashLeftParen.
   759             ^ tokenType
   759 	    ^ tokenType
   760         ].
   760 	].
   761         (nextChar == $[ ) ifTrue:[
   761 	(nextChar == $[ ) ifTrue:[
   762             "it seems that ST-80 supports Constant ByteArrays as #[...]
   762 	    "it seems that ST-80 supports Constant ByteArrays as #[...]
   763              (seen in a PD program)"
   763 	     (seen in a PD program)"
   764             source next.
   764 	    source next.
   765             tokenType := #HashLeftBrack.
   765 	    tokenType := #HashLeftBrack.
   766             ^ tokenType
   766 	    ^ tokenType
   767         ].
   767 	].
   768         (nextChar == $' ) ifTrue:[
   768 	(nextChar == $' ) ifTrue:[
   769             "it seems that ST-80 supports arbitrary symbols as #'...'
   769 	    "it seems that ST-80 supports arbitrary symbols as #'...'
   770              (seen in a PD program)"
   770 	     (seen in a PD program)"
   771             self nextString.
   771 	    self nextString.
   772             tokenValue := tokenValue asSymbol.
   772 	    tokenValue := tokenValue asSymbol.
   773             tokenType := #Symbol.
   773 	    tokenType := #Symbol.
   774             ^ tokenType
   774 	    ^ tokenType
   775         ].
   775 	].
   776         ((TypeArray at:(nextChar asciiValue)) == #special) ifTrue:[
   776 	((TypeArray at:(nextChar asciiValue)) == #special) ifTrue:[
   777             string := source next asString.
   777 	    string := source next asString.
   778             nextChar := source peek.
   778 	    nextChar := source peek.
   779             nextChar notNil ifTrue:[
   779 	    nextChar notNil ifTrue:[
   780                 ((TypeArray at:(nextChar asciiValue)) == #special) ifTrue:[
   780 		((TypeArray at:(nextChar asciiValue)) == #special) ifTrue:[
   781                     source next.
   781 		    source next.
   782                     string := string copyWith:nextChar
   782 		    string := string copyWith:nextChar
   783                 ]
   783 		]
   784             ].
   784 	    ].
   785             tokenValue := string asSymbol.
   785 	    tokenValue := string asSymbol.
   786             tokenType := #Symbol.
   786 	    tokenType := #Symbol.
   787             ^ tokenType
   787 	    ^ tokenType
   788         ]
   788 	]
   789     ].
   789     ].
   790     "this allows hash to be used as binop -
   790     "this allows hash to be used as binop -
   791      I dont know, if this is correct ..."
   791      I dont know, if this is correct ..."
   792 
   792 
   793     tokenName := '#'.
   793     tokenName := '#'.
   794     tokenType := BinaryOperator.
   794     tokenType := #BinaryOperator.
   795     ^ tokenType
   795     ^ tokenType
   796 "
   796 "
   797     self syntaxError:'unexpected end-of-input in Symbol'
   797     self syntaxError:'unexpected end-of-input in Symbol'
   798             position:tokenPosition to:(tokenPosition + 1).
   798 	    position:tokenPosition to:(tokenPosition + 1).
   799     ^ #Error
   799     ^ #Error
   800 "
   800 "
   801 !
   801 !
   802 
   802 
   803 nextString
   803 nextString
   813     source next.
   813     source next.
   814     nextChar := source next.
   814     nextChar := source next.
   815     inString := true.
   815     inString := true.
   816 
   816 
   817     [inString] whileTrue:[
   817     [inString] whileTrue:[
   818         nextChar isNil ifTrue:[
   818 	nextChar isNil ifTrue:[
   819             self syntaxError:'unexpected end-of-input in String'
   819 	    self syntaxError:'unexpected end-of-input in String'
   820                     position:pos to:(source position - 1).
   820 		    position:pos to:(source position - 1).
   821             tokenType := #EOF.
   821 	    tokenType := #EOF.
   822             ^ tokenType
   822 	    ^ tokenType
   823         ].
   823 	].
   824         (nextChar == Character cr) ifTrue:[
   824 	(nextChar == Character cr) ifTrue:[
   825             tokenLineNr := tokenLineNr + 1
   825 	    tokenLineNr := tokenLineNr + 1
   826         ].
   826 	].
   827         (nextChar == Character quote) ifTrue:[
   827 	(nextChar == Character quote) ifTrue:[
   828             (source peek == Character quote) ifTrue:[
   828 	    (source peek == Character quote) ifTrue:[
   829                 source next
   829 		source next
   830             ] ifFalse:[
   830 	    ] ifFalse:[
   831                 inString := false
   831 		inString := false
   832             ]
   832 	    ]
   833         ].
   833 	].
   834         inString ifTrue:[
   834 	inString ifTrue:[
   835             string at:index put:nextChar.
   835 	    string at:index put:nextChar.
   836             (index == len) ifTrue:[
   836 	    (index == len) ifTrue:[
   837                 string := string , (String new:len).
   837 		string := string , (String new:len).
   838                 len := len * 2
   838 		len := len * 2
   839             ].
   839 	    ].
   840             index := index + 1.
   840 	    index := index + 1.
   841             nextChar := source next
   841 	    nextChar := source next
   842         ]
   842 	]
   843     ].
   843     ].
   844     tokenValue := string copyTo:(index - 1).
   844     tokenValue := string copyTo:(index - 1).
   845     tokenType := #String.
   845     tokenType := #String.
   846     ^ tokenType
   846     ^ tokenType
   847 ! !
   847 ! !