'From Cuis 2.0 of 4 January 2010 [latest update: #393] on 11 January 2010 at 10:14:28 pm'!

!SHParserST80 methodsFor: 'parse' stamp: 'nice 11/30/2009 11:36'!
parseByteArray
	[currentTokenFirst == $]] whileFalse: [
		currentTokenFirst isDigit 
			ifTrue: [
				"do not parse the number, can be time consuming"
				self scanPast: #number]
			ifFalse: [
				self failWhen: currentTokenFirst == $. .
				self error]].
	self scanPast: #arrayEnd! !

!SHParserST80 methodsFor: 'parse' stamp: 'nice 12/27/2009 03:12'!
parseKeyword 
    | keyword rangeIndices |
    self parseBinary.
	keyword := ''.
	rangeIndices := #().
	[
    		[self isKeyword]
        		whileTrue: [
				keyword := keyword, currentToken. 
				self rangeType: #keyword.
				"remember where this keyword token is in ranges"
				rangeIndices := rangeIndices copyWith: ranges size.
				self scanNext.
				self parseTerm.
				self parseBinary ]
	] ensure: [ | type |
		"do this in an ensure so that it happens even if the errorBlock evaluates before getting here"
		"patch up the keyword tokens, so that incomplete and undefined ones look different"
		(keyword isEmpty or:[Symbol hasInterned: keyword ifTrue: [:sym | ]])
			ifFalse:[
				type := (Symbol thatStartsCaseSensitive: keyword skipping: nil) isNil
					ifTrue: [#undefinedKeyword]
					ifFalse:[#incompleteKeyword].
				rangeIndices do: [:i | (ranges at: i) type: type]]]! !

!SHParserST80 methodsFor: 'parse' stamp: 'nice 11/30/2009 11:34'!
parseSymbol
	| c |
	currentToken = '#' 
		ifTrue: [
			"if token is just the #, then scan whitespace and comments
			and then process the next character.
			Squeak allows space between the # and the start of the symbol 
			e.g. # (),  #  a, #  'sym' "
			self rangeType: #symbol.
			self scanWhitespace].
	c := self currentChar.
	self failWhen: (c isNil or: [c isSeparator]).
	c == $( 
		ifTrue: [
			self nextChar.
			self scanPast: #arrayStart start: currentTokenSourcePosition end: currentTokenSourcePosition + 1.
			^self parseArray].
	c == $' ifTrue: [^self parseSymbolString].
	c == $[ ifTrue: [
			self nextChar.
			self scanPast: #arrayStart start: currentTokenSourcePosition end: currentTokenSourcePosition + 1.
			^self parseByteArray].
	((self isSelectorCharacter: c) or: [c == $-]) 
		ifTrue: [^self parseSymbolSelector].
	(c isLetter or: [c == $:]) ifTrue: [^self parseSymbolIdentifier].
	^self parseCharSymbol! !


!SHTextStylerST80 methodsFor: 'private' stamp: 'nice 12/27/2009 03:12'!
replaceStringForRangesWithType: aSymbol with: aString in: aText 
	"Answer aText if no replacements, or a copy of aText with 
	each range with a type of aSymbol replaced by aString"
	| answer toReplace adjustSourceMap increaseInLength |
	
	toReplace := (self rangesIn: aText setWorkspace: false) 
		select: [:each | each type = aSymbol].
	toReplace isEmpty ifTrue: [^aText].
	answer := aText copy.
	increaseInLength := 0.
	adjustSourceMap := sourceMap notNil and:[sourceMap ~~ processedSourceMap].
	(toReplace asSortedCollection: [:a :b | a start <= b start]) 
		do: [:each | | end start thisIncrease | 
			start := each start + increaseInLength.
			end := each end + increaseInLength.
			answer 	replaceFrom: start to: end with: aString.
			thisIncrease := aString size - each length.
			increaseInLength := increaseInLength + thisIncrease.
			adjustSourceMap ifTrue:[
				sourceMap do:[:assoc | | first newFirst last newLast |
					first := newFirst := assoc value first.
					last := newLast := assoc value last.
					first > start ifTrue:[newFirst := first + thisIncrease].
					last > start ifTrue:[newLast := last + thisIncrease].
					(first ~= newFirst or:[last ~= newLast])
						ifTrue:[assoc value: (newFirst to: newLast)]]]].
	adjustSourceMap ifTrue:[processedSourceMap := sourceMap]. 
	^answer! !

