'From Cuis 2.3 of 22 March 2010 [latest update: #472] on 14 April 2010 at 1:32:22 pm'!

!Preferences class methodsFor: 'shout' stamp: 'jmv 4/14/2010 10:17'!
syntaxHighlightingAsYouTypeLeftArrowAssignment
	^ self
		valueOfFlag: #syntaxHighlightingAsYouTypeLeftArrowAssignment
		ifAbsent: [ false ]! !


!SHParserST80 methodsFor: 'scan' stamp: 'jmv 4/14/2010 11:54'!
scanIdentifier
	| c start |
	start _ sourcePosition.
	[ self isValidInIdentifiers: (c _ self nextChar) ] whileTrue: [].
	(c == $: and: [(self isSelectorCharacter: self peekChar) not]) 
		ifTrue: [self nextChar].
	currentToken _ source copyFrom: start to: sourcePosition - 1.
	currentTokenSourcePosition _ start! !

!SHParserST80 methodsFor: 'scan' stamp: 'jmv 4/14/2010 11:55'!
scanNext
	self scanWhitespace.
	currentTokenFirst _ self currentChar.
	currentTokenFirst 
		ifNil: [" end of input "
			currentTokenFirst _ $ .
			currentTokenSourcePosition _ nil.
			currentToken _ nil.
			^nil].
	currentTokenFirst isDigit ifTrue: [^self scanNumber].
	(self isValidStartOfIdentifiers: currentTokenFirst) ifTrue: [^self scanIdentifier].
	^self scanBinary! !

!SHParserST80 methodsFor: 'token testing' stamp: 'jmv 4/14/2010 09:16'!
isAssignment
	^currentToken = ':=' or: [ currentToken = '_' and: [ self allowUnderscoreAssignments ]]! !

!SHParserST80 methodsFor: 'token testing' stamp: 'jmv 4/14/2010 11:55'!
isKeyword
	^(self isValidStartOfIdentifiers: currentTokenFirst) and: [currentToken last == $:]! !

!SHParserST80 methodsFor: 'token testing' stamp: 'jmv 4/14/2010 11:55'!
isName
	^(self isValidStartOfIdentifiers: currentTokenFirst) and: [ self isValidInIdentifiers: currentToken last ]! !

!SHParserST80 methodsFor: 'character testing' stamp: 'jmv 4/14/2010 11:54'!
isSelectorCharacter: aCharacter
	"Actually meaning 'isBinarySelectorCharacter'. i.e. can aCharacter be part of a binary selector? "
	(self isValidInIdentifiers: aCharacter) ifTrue: [^false].
	aCharacter isSeparator ifTrue:[^false].
	"$- is specified here as NOT being a selector char, but it can appear as the 
	first char in a binary selector. That case is handled specially elsewhere"
	('"#$'':().;[]{}^_-'  includes: aCharacter) 
		ifTrue:[^false].
	aCharacter asciiValue = 30 ifTrue: [^false "the doIt char"].
	aCharacter asciiValue = 0 ifTrue: [^false].
	"Any other char is ok as a binary selector char."
	^true
! !

!SHParserST80 methodsFor: 'character testing' stamp: 'jmv 4/14/2010 11:54'!
isValidInIdentifiers: c
	"Can c be part of an identifier? (unary or keyword selector, or variable name)"
	^c isAlphaNumeric or: [ c  = $_ and: [ self allowUnderscoreSelectors ]]! !

!SHParserST80 methodsFor: 'character testing' stamp: 'jmv 4/14/2010 11:54'!
isValidStartOfIdentifiers: c
	"Can c be the first character of an identifier? (unary or keyword selector, or variable name)"
	^c isLetter or: [ c  = $_ and: [ self allowUnderscoreSelectors ]]! !

!SHParserST80 methodsFor: 'parse' stamp: 'jmv 4/14/2010 11:55'!
parseLiteralArrayElement
	(self isValidStartOfIdentifiers: currentTokenFirst)
		ifTrue: [
			| type |
			type _ (#('true' 'false' 'nil') includes: currentToken) 
				ifTrue: [currentToken asSymbol]
				ifFalse: [#symbol].
			^self scanPast: type].
	currentTokenFirst == $( 
		ifTrue: [
			self scanPast: #arrayStart.
			^self parseArray].
	^self parseLiteral: true! !

!SHParserST80 methodsFor: 'parse' stamp: 'jmv 4/14/2010 11:55'!
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].
	((self isValidStartOfIdentifiers: c) or: [c == $:]) ifTrue: [^self parseSymbolIdentifier].
	^self parseCharSymbol! !

!SHParserST80 methodsFor: 'parse' stamp: 'jmv 4/14/2010 11:55'!
parseSymbolIdentifier
	| c start end |
	c _ self currentChar.
	self failUnless: ((self isValidStartOfIdentifiers: c) or: [ c == $: ]).
	start _ sourcePosition.	
	[c _ self nextChar.
	(self isValidInIdentifiers: c) or: [ c == $: ]] 
		whileTrue: [].
	end _ sourcePosition - 1.
	c _ source copyFrom: start - 1 to: end.
	self scanPast: #symbol start: start - 1 end: end.
	^c! !

!SHParserST80 methodsFor: 'aux' stamp: 'jmv 4/14/2010 09:36'!
allowUnderscoreAssignments
	"Query class + preference.
	Please see comments in Scanner >> #allowUnderscoreAssignments"
	^(classOrMetaClass ifNotNil: [classOrMetaClass allowUnderscoreAssignments])
		ifNil:[ Preferences allowUnderscoreAssignments ]! !

!SHParserST80 methodsFor: 'aux' stamp: 'jmv 4/14/2010 09:36'!
allowUnderscoreSelectors
	"Query class + preference.
	Please see comments in Scanner >> #allowUnderscoreSelectors"
	^(classOrMetaClass ifNotNil: [classOrMetaClass allowUnderscoreSelectors])
		ifNil:[ Preferences allowUnderscoreSelectors ]! !

SHParserST80 removeSelector: #isIdentifierCharacter:!
SHParserST80 removeSelector: #isIdentifierStartCharacter:!
"Postscript:
Leave the line above, and replace the rest of this comment by a useful one.
Executable statements should follow this comment, and should
be separated by periods, with no exclamation points (!!).
Be sure to put any further comments in double-quotes, like this one."
Preferences setPreference: #syntaxHighlightingAsYouTypeLeftArrowAssignment toValue: false!

