
A little light exercise ...
John,
Quote:
> My stab is below. It includes some extensions to ReadStream (is this
> allowed?), although it would be more appropriate to create a dedicated
> subclass.
The only rule was that there are no rules <g>
Quote:
> It's an interesting excerise; in particular I hadn't considered the use of
> comments in a method selector, e.g. WebBrowserShell>>OnBeforeNavigate2...
Yes, that's the one that caught me. One other way in which your code fails
(there are no instances of this in the image so I suppose it's not really
applicable to this thread) is if there is any whitespace before the first
character. Easily fixed by a couple of small changes to #firstSection.
One other thing I thought of while writing this - comments *before* the
selector are legitimate and compile correctly. No one would do that
though - would they <g>
I also found the exercise interesting, which was why I mentioned it in the
group. My first version, in the original ChunkBrowser, used Streams but I
thought that a version that accessed the String directly would be quicker. I
was surprised to find that not only was there little difference in speed but
the non-stream version was much more complicated than I expected. I've
posted it below, but please wear protective glasses before looking at it.
I think I'll go back to a stream version for the ChunkBrowser though, the
slight difference in performance is probably not worth the ugly code!!
Regards
Ian
"Filed out from Dolphin Smalltalk 2000 release 4.01"!
Parser subclass: #IanParser
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''!
IanParser comment: ''!
IanParser guid: (GUID fromString: '{0CE35693-FC18-4002-8DD5-518C96D32430}')!
!IanParser categoriesForClass!Unclassified! !
!IanParser methodsFor!
parse: aString
| position positionEnd selector |
selector := String new.
position := 1.
"skip whitespace"
[(aString at: position) isSeparator] whileTrue: [position := position +
1].
"just a selector"
positionEnd := (position to: aString size)
detect: [:i | (self validSelectorCharacters includes: (aString at:
i)) not]
ifNone: [0].
positionEnd = 0 ifTrue: [^aString copyFrom: position].
"One of the operators or a selector with no args"
(aString at: positionEnd) = $:
ifFalse: [^aString copyFrom: position to: positionEnd - 1].
"A selector with an argument so iterate, picking up the selector but
ignoring the args"
selector := aString copyFrom: position to: positionEnd.
position := positionEnd.
[ "skip whitespace (starting from :)"
[position := position + 1.
(aString at: position) isSeparator] whileTrue.
"skip argument"
position := (position to: aString size)
detect: [:i | (self validArgumentCharacters includes: (aString
at: i)) not]
ifNone: [^selector].
"skip whitespace (starting from )"
[(aString at: position) isSeparator] whileTrue: [position :=
position + 1].
"skip comments"
[position < aString size and: [(aString at: position) = $"]]
whileTrue: [
position := position + 1.
[(aString at: position) = $"] whileFalse: [position := position
+ 1].
position := position + 1.
[position < aString size and: [(aString at: position)
isSeparator]]
whileTrue: [position := position + 1]].
"possibly the next part of a selector - nb use argument characters
for
selector now"
positionEnd := (position to: aString size)
detect: [:i | (self validArgumentCharacters includes: (aString
at: i)) not]
ifNone: [^selector].
"Not a : means that we have found the start of the method text so
use what
we have"
(aString at: positionEnd) = $: ifFalse: [^selector].
"Append the new part of the selector and continue"
selector := selector , (aString copyFrom: position to: positionEnd).
position := positionEnd] repeat.
self halt "shouldn't get here"!
validArgumentCharacters
^'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'!
validSelectorCharacters
^'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~_->=<|&,+*/
!IanParser categoriesFor: #parse:!*-unclassified!public! !
!IanParser categoriesFor: #validArgumentCharacters!*-unclassified!public! !
!IanParser categoriesFor: #validSelectorCharacters!*-unclassified!public! !