[squeak-dev] The Inbox: OMeta2-Preload-yo.15.mcz

Yoshiki Ohshima Yoshiki.Ohshima at acm.org
Thu Jul 31 20:34:44 UTC 2014


Hmm, ok.  This diff has more code than it should have, but I patched
OMeta2 package to make it work in the new compiler regime in Squeak
4.5.  Hans-Martin, do you think you can take this, and update the
config map (if necessary)?

On Thu, Jul 31, 2014 at 1:31 PM,  <commits at source.squeak.org> wrote:
> A new version of OMeta2-Preload was added to project The Inbox:
> http://source.squeak.org/inbox/OMeta2-Preload-yo.15.mcz
>
> ==================== Summary ====================
>
> Name: OMeta2-Preload-yo.15
> Author: yo
> Time: 31 July 2014, 1:29:01.319 pm
> UUID: 6c6bc75e-3c9f-4446-b08a-cdce7081ef2d
> Ancestors: OMeta2-Preload-hmm.14
>
> Adapt to Squeak 4.5.
>
> ==================== Snapshot ====================
>
> SystemOrganization addCategory: #OMeta2!
> SystemOrganization addCategory: #'OMeta2-Info'!
>
> ----- Method: CompiledMethod>>methodNode (in category '*OMeta2-Preload') -----
> methodNode
>         "Return the parse tree that represents self. If parsing fails, decompile the method."
>         | aClass source |
>         aClass := self methodClass.
>         source := self
>                                 getSourceFor: (self selector ifNil: [self defaultSelector])
>                                 in: aClass.
>         ^[(aClass parserClass new
>                 encoderClass: (self isBlueBookCompiled
>                                                 ifTrue: [EncoderForV3]
>                                                 ifFalse: [EncoderForV3PlusClosures]);
>                 parse: source class: aClass)
>                         sourceText: source;
>                         yourself]
>                 on: SyntaxErrorNotification
>                 do: [:ex | ex return: self decompile].!
>
> Exception subclass: #OM2Fail
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OM2Fail class>>initialize (in category 'class initialization') -----
> initialize
>         (Smalltalk at: #OMeta2Fail ifAbsent: []) class == self
>                 ifFalse: [Smalltalk at: #OMeta2Fail put: self new]!
>
> ----- Method: OM2Fail>>defaultAction (in category 'priv handling') -----
> defaultAction
>
>         self error: 'match failed'!
>
> MethodReference subclass: #OM2DecompilingMethodReference
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2-Info'!
>
> !OM2DecompilingMethodReference commentStamp: 'hmm 5/24/2010 13:15' prior: 0!
> This class is a helper to OM2PreloadPackagingInfo which is used to save OMeta2 productions in their decompiled form.!
>
> ----- Method: OM2DecompilingMethodReference>>source (in category 'queries') -----
> source
>         ^self compiledMethod decompileString!
>
> Compiler subclass: #OMeta2Compiler
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OMeta2Compiler>>compile:in:notifying:ifFail: (in category 'as yet unclassified') -----
> compile: origCode in: cls notifying: notify ifFail: failBlock
>
>         | origCodeStream parseTree structuredCode translatedCode |
>         origCodeStream := origCode asString readStream.
>         [
>                 parseTree := OMeta2RuleParser matchStream: origCodeStream with: #rule withArgs: #() withPlaybackDebugging: false.
>                 parseTree := OMeta2Optimizer match: parseTree with: #optimizeRule.
>                 structuredCode := OMeta2RuleTranslator match: parseTree with: #translate withArgs: {cls}.
>                 translatedCode := OMeta2Flattener match: structuredCode with: #flatten
>         ] on: OM2Fail do: [
>                 self notify: '<-- parse error around here -->' at: origCodeStream position.
>                 ^ failBlock value
>         ].
>         ^ super compile: translatedCode in: cls notifying: notify ifFail: failBlock.
> !
>
> ----- Method: OMeta2Compiler>>parse:class:noPattern:context:notifying:ifFail: (in category 'as yet unclassified') -----
> parse: aStream class: aClass noPattern: noPattern context: ctxt notifying: req ifFail: aBlock
>         | node |
>         ^ [
>                 | parseTree structuredCode code |
>                 parseTree := OMeta2RuleParser matchAll: aStream contents with: #rule.
>                 structuredCode := OMeta2RuleTranslator match: parseTree with: #translate withArgs: {aClass}.
>                 code := OMeta2Flattener match: structuredCode with: #flatten.
>                 node := Parser new parse: code readStream class: aClass noPattern: noPattern context: ctxt notifying: req ifFail: aBlock.
>                 OMeta2MethodNode adoptInstance: node.
>                 node
>         ] on: OM2Fail do: [aBlock value]!
>
> ----- Method: OMeta2Compiler>>parse:in:notifying: (in category 'as yet unclassified') -----
> parse: origCode in: aClass notifying: req
>         | c parseTree structuredCode translatedCode origCodeStream |
>         origCodeStream := origCode asString readStream.
>
>         parseTree := OMeta2RuleParser matchStream: origCodeStream with: #rule withArgs: #() withPlaybackDebugging: false.
>         parseTree := OMeta2Optimizer match: parseTree with: #optimizeRule.
>         structuredCode := OMeta2RuleTranslator match: parseTree with: #translate withArgs: {aClass}.
>         translatedCode := OMeta2Flattener match: structuredCode with: #flatten.
>
>         c := CompilationCue
>                         source: translatedCode
>                         class: aClass
>                         requestor: req.
>         ^ self
>                 parseCue: c
>                 noPattern: false
>                 ifFail: nil!
>
> ----- Method: OMeta2Compiler>>parseCue:noPattern:ifFail: (in category 'as yet unclassified') -----
> parseCue: aCue noPattern: noPattern ifFail: aBlock
>         ^ Parser new parseCue: aCue noPattern: noPattern ifFail: aBlock
> !
>
> ----- Method: OMeta2Compiler>>parser (in category 'as yet unclassified') -----
> parser
>         ^ self parserClass new!
>
> ----- Method: OMeta2Compiler>>parserClass (in category 'as yet unclassified') -----
> parserClass
>
>         ^ self class!
>
> PackageInfo subclass: #OM2PostloadPackageInfo
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2-Info'!
>
> !OM2PostloadPackageInfo commentStamp: 'hmm 4/16/2010 17:09' prior: 0!
> This class stores all OMeta2 production rules in their original format.!
>
> ----- Method: OM2PostloadPackageInfo class>>initialize (in category 'class initialization') -----
> initialize
>         self new register!
>
> ----- Method: OM2PostloadPackageInfo>>classes (in category 'listing') -----
> classes
>         ^super classes select: [:each | each inheritsFrom: OMeta2Base]!
>
> ----- Method: OM2PostloadPackageInfo>>coreMethodsForClass: (in category 'testing') -----
> coreMethodsForClass: aClass
>         MCMethodDefinition shutDown.    "flush cache so pre- and postload don't interfere"
>         ^(super coreMethodsForClass: aClass) select: [:each | OMeta2RuleParser isOMeta2Rule: each source]!
>
> ----- Method: OM2PostloadPackageInfo>>extensionMethodsForClass: (in category 'testing') -----
> extensionMethodsForClass: aClass
>         ^#()!
>
> ----- Method: OM2PostloadPackageInfo>>packageName (in category 'naming') -----
> packageName
>         ^super packageName, '-Postload'!
>
> ----- Method: OM2PostloadPackageInfo>>systemCategoryPrefix (in category 'naming') -----
> systemCategoryPrefix
>         ^super packageName!
>
> PackageInfo subclass: #OM2PreloadPackageInfo
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2-Info'!
>
> !OM2PreloadPackageInfo commentStamp: 'hmm 4/16/2010 17:08' prior: 0!
> This class makes it possible to store OMeta2 using decompiled production rules, so that it can be loaded without being present first.
> It uses OM2DecompilingMethodReference to decompile OMeta2 rules on the fly while creating a source file.!
>
> ----- Method: OM2PreloadPackageInfo class>>initialize (in category 'class initialization') -----
> initialize
>         self new register!
>
> ----- Method: OM2PreloadPackageInfo>>packageName (in category 'naming') -----
> packageName
>         ^super packageName, '-Preload'!
>
> ----- Method: OM2PreloadPackageInfo>>referenceForMethod:ofClass: (in category 'listing') -----
> referenceForMethod: aSymbol ofClass: aClass
>         MCMethodDefinition shutDown.    "flush cache so pre- and postload don't interfere"
>         ^((OMeta2RuleParser isOMeta2Rule: (aClass sourceCodeAt: aSymbol))
>                 ifTrue: [OM2DecompilingMethodReference]
>                 ifFalse: [MethodReference]) new setStandardClass: aClass methodSymbol: aSymbol!
>
> ----- Method: OM2PreloadPackageInfo>>systemCategoryPrefix (in category 'naming') -----
> systemCategoryPrefix
>         ^super packageName!
>
> Object subclass: #OM2Failer
>         instanceVariableNames: 'used'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OM2Failer>>initialize (in category 'initialize-release') -----
> initialize
>
>         used := false!
>
> ----- Method: OM2Failer>>used (in category 'testing') -----
> used
>
>         ^ used!
>
> ----- Method: OM2Failer>>value (in category 'evaluating') -----
> value
>
>         used := true.
>         OMeta2Fail signal!
>
> Object subclass: #OM2Stream
>         instanceVariableNames: 'head tail memo'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> OM2Stream subclass: #OM2EndOfStream
>         instanceVariableNames: 'stream pos'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OM2EndOfStream>>head (in category 'accessing') -----
> head
>
>         OMeta2Fail signal!
>
> ----- Method: OM2EndOfStream>>initStream:pos: (in category 'initialize-release') -----
> initStream: s pos: p
>
>         stream := s.
>         pos := p!
>
> ----- Method: OM2EndOfStream>>inputSpecies (in category 'accessing') -----
> inputSpecies
>
>         ^ stream originalContents species!
>
> ----- Method: OM2EndOfStream>>pos (in category 'accessing') -----
> pos
>
>         ^ pos!
>
> ----- Method: OM2EndOfStream>>tail (in category 'accessing') -----
> tail
>
>         OMeta2Fail signal!
>
> OM2Stream subclass: #OM2LazyStream
>         instanceVariableNames: 'stream pos'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OM2LazyStream class>>for:withPos: (in category 'as yet unclassified') -----
> for: aReadStream withPos: pos
>
>         ^ aReadStream atEnd
>                 ifTrue: [OM2EndOfStream new initStream: aReadStream pos: pos]
>                 ifFalse: [self new initHead: aReadStream next stream: aReadStream pos: pos]!
>
> ----- Method: OM2LazyStream>>initHead:stream:pos: (in category 'initialize-release') -----
> initHead: h stream: s pos: p
>
>         head := h.
>         stream := s.
>         pos := p!
>
> ----- Method: OM2LazyStream>>inputSpecies (in category 'accessing') -----
> inputSpecies
>
>         ^ stream originalContents species!
>
> ----- Method: OM2LazyStream>>pos (in category 'accessing') -----
> pos
>
>         ^ pos!
>
> ----- Method: OM2LazyStream>>tail (in category 'accessing') -----
> tail
>
>         tail ifNil: [tail := OM2LazyStream for: stream withPos: pos + 1].
>         ^ tail!
>
> ----- Method: OM2Stream>>basicTail (in category 'accessing') -----
> basicTail
>
>         ^ tail!
>
> ----- Method: OM2Stream>>forgetEverything (in category 'forgetting') -----
> forgetEverything
>
>         memo := IdentityDictionary new!
>
> ----- Method: OM2Stream>>head (in category 'accessing') -----
> head
>
>         ^ head!
>
> ----- Method: OM2Stream>>initHead:tail: (in category 'initialize-release') -----
> initHead: h tail: t
>
>         head := h.
>         tail := t!
>
> ----- Method: OM2Stream>>initialize (in category 'initialize-release') -----
> initialize
>
>         memo := IdentityDictionary new!
>
> ----- Method: OM2Stream>>inputSpecies (in category 'accessing') -----
> inputSpecies
>
>         ^ Array!
>
> ----- Method: OM2Stream>>memo (in category 'accessing') -----
> memo
>
>         ^ memo!
>
> ----- Method: OM2Stream>>pos (in category 'accessing') -----
> pos
>
>         ^ -1!
>
> ----- Method: OM2Stream>>printOn: (in category 'printing') -----
> printOn: aStream
>
>         | inputIsString curr |
>         inputIsString := (self inputSpecies inheritsFrom: String) and: [(self inputSpecies inheritsFrom: Symbol) not].
>         curr := self.
>         aStream
>                 nextPutAll: 'an ';
>                 nextPutAll: self class name;
>                 nextPut: $(.
>         [curr notNil] whileTrue: [
>                 (curr isKindOf: OM2EndOfStream) ifTrue: [
>                         aStream nextPut: $).
>                         ^ self
>                 ].
>                 inputIsString
>                         ifTrue: [aStream nextPut: curr head]
>                         ifFalse: [
>                                 curr head printOn: aStream.
>                                 aStream space
>                         ].
>                 curr := curr basicTail.
>         ].
>         aStream nextPutAll: '...)'!
>
> ----- Method: OM2Stream>>tail (in category 'accessing') -----
> tail
>
>         ^ tail!
>
> ----- Method: OM2Stream>>transitiveForgetEverything (in category 'forgetting') -----
> transitiveForgetEverything
>
>         | curr |
>         curr := self.
>         [curr notNil] whileTrue: [
>                 curr forgetEverything.
>                 curr := curr basicTail
>         ]!
>
> OM2Stream subclass: #OM2StreamDebugger
>         instanceVariableNames: 'om2stream'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OM2StreamDebugger class>>for: (in category 'as yet unclassified') -----
> for: anOM2Stream
>
>         ^ self new initOm2stream: anOM2Stream!
>
> ----- Method: OM2StreamDebugger>>forgetEverything (in category 'forgetting') -----
> forgetEverything
>
>         om2stream forgetEverything!
>
> ----- Method: OM2StreamDebugger>>head (in category 'accessing') -----
> head
>
>         ^ om2stream head!
>
> ----- Method: OM2StreamDebugger>>initOm2stream: (in category 'initialize-release') -----
> initOm2stream: anOM2Stream
>
>         om2stream := anOM2Stream!
>
> ----- Method: OM2StreamDebugger>>memo (in category 'accessing') -----
> memo
>
>         ^ om2stream memo!
>
> ----- Method: OM2StreamDebugger>>printOn: (in category 'printing') -----
> printOn: aStream
>
>         aStream nextPutAll: 'an OM2StreamDebugger('.
>         om2stream printOn: aStream.
>         aStream nextPut: $)!
>
> ----- Method: OM2StreamDebugger>>tail (in category 'accessing') -----
> tail
>
>         ^ om2stream tail!
>
> ----- Method: OM2StreamDebugger>>transitiveForgetEverything (in category 'forgetting') -----
> transitiveForgetEverything
>
>         om2stream transitiveForgetEverything!
>
> OM2Stream subclass: #OM2StreamProxy
>         instanceVariableNames: 'target'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OM2StreamProxy class>>for: (in category 'as yet unclassified') -----
> for: anOM2Stream
>
>         ^ self new initTarget: anOM2Stream!
>
> ----- Method: OM2StreamProxy>>basicTail (in category 'accessing') -----
> basicTail
>
>         ^ target basicTail!
>
> ----- Method: OM2StreamProxy>>head (in category 'accessing') -----
> head
>
>         head ifNil: [head := target head].
>         ^ head
> !
>
> ----- Method: OM2StreamProxy>>initTarget: (in category 'initialize-release') -----
> initTarget: anOM2Stream
>
>         target := anOM2Stream!
>
> ----- Method: OM2StreamProxy>>inputSpecies (in category 'accessing') -----
> inputSpecies
>
>         ^ target inputSpecies!
>
> ----- Method: OM2StreamProxy>>pos (in category 'accessing') -----
> pos
>
>         ^ target pos!
>
> ----- Method: OM2StreamProxy>>tail (in category 'accessing') -----
> tail
>
>         tail ifNil: [tail := OM2StreamProxy for: target tail].
>         ^ tail!
>
> ----- Method: OM2StreamProxy>>target (in category 'accessing') -----
> target
>
>         ^ target!
>
> Object subclass: #OMeta2Base
>         instanceVariableNames: 'input om2streams haltingPoint'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> OMeta2Base subclass: #OMeta2
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> !OMeta2 commentStamp: '<historical>' prior: 0!
> TODOS:
>
> * implement OMeta -> Squeak translator
> * implement Squeak parser
> * implement OMeta/Squeak "compiler", make it OMeta2's compilerClass
>
> * rewrite #char, #digit, #empty, #end, #exactly, #firstAndRest, #fromTo, #letter, #letterOrDigit, #listOf, #lower, #notLast, #number, #range, #space, #spaces, #string, #symbol, #token, and #upper in OMeta syntax
> * consider implementing position-related functionality (see http://www.tinlizzie.org/ometa-js/ometa-base.js)
> * consider the optimization suggestions in the comments of OMeta2Lib's methods!
>
> OMeta2 subclass: #O2SqueakRecognizer
>         instanceVariableNames: ''
>         classVariableNames: 'TypeTable'
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: O2SqueakRecognizer class>>initialize (in category 'as yet unclassified') -----
> initialize
>
>         TypeTable := #(#xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xDelimiter #xDelimiter #xBinary #xDelimiter #xDelimiter #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #doIt #xBinary #xDelimiter #xBinary #xDoubleQuote #xLitQuote #xDollar #xBinary #xBinary #xSingleQuote #leftParenthesis #rightParenthesis #xBinary #xBinary #xBinary #xBinary #period #xBinary #xDigit #xDigit #xDigit #xDigit #xDigit #xDigit #xDigit #xDigit #xDigit #xDigit #xColon #semicolon #xBinary #xBinary #xBinary #xBinary #xBinary #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #leftBracket #xBinary #rightBracket #upArrow #leftArrow #xBinary #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLe
>  tter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #leftBrace #verticalBar #rightBrace #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xLetter #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xBinary #xLetter #xBinary #xBinary #xBinary #xBinary #xLetter #xBinary #xBinary #xBinary #xBinary #xBinary #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #x
>  Binary #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xBinary #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xLetter #xBinary)!
>
> ----- Method: O2SqueakRecognizer>>arrayConstr (in category 'rules-parsing') -----
> arrayConstr
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #token withArgs: {'{'}.
>                                 self apply: #expr.
>                                 self
>                                         many: [true
>                                                         ifTrue: [self apply: #token withArgs: {'.'}.
>                                                                 self apply: #expr]].
>                                 self ometaOr: {[self apply: #token withArgs: {'.'}]. [self apply: #empty]}.
>                                 self apply: #token withArgs: {'}'}]]. [true
>                         ifTrue: [self apply: #token withArgs: {'{'}.
>                                 self apply: #token withArgs: {'}'}]]}!
>
> ----- Method: O2SqueakRecognizer>>arrayLit (in category 'rules-parsing') -----
> arrayLit
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {'#'}.
>                         self apply: #token withArgs: {'('}.
>                         self
>                                 many: [self ometaOr: {[self apply: #literal]. [self apply: #arrayLit]. [true
>                                                         ifTrue: [self apply: #spaces.
>                                                                 self apply: #tsArraySymbol]]}].
>                         self apply: #token withArgs: {')'}]!
>
> ----- Method: O2SqueakRecognizer>>binary (in category 'rules-parsing') -----
> binary
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self apply: #tsBinary]!
>
> ----- Method: O2SqueakRecognizer>>binaryExpr (in category 'rules-parsing') -----
> binaryExpr
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #binaryExpr.
>                                 self apply: #binaryMsg]]. [self apply: #unaryExpr]}!
>
> ----- Method: O2SqueakRecognizer>>binaryMsg (in category 'rules-parsing') -----
> binaryMsg
>         ^ true
>                 ifTrue: [self apply: #binary.
>                         self apply: #unaryExpr]!
>
> ----- Method: O2SqueakRecognizer>>block (in category 'rules-parsing') -----
> block
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {'['}.
>                         self ometaOr: {[true
>                                         ifTrue: [self
>                                                         many1: [true
>                                                                         ifTrue: [self apply: #token withArgs: {':'}.
>                                                                                 self apply: #identifier]].
>                                                 self apply: #token withArgs: {'|'}]]. [self apply: #empty]}.
>                         self ometaOr: {[true
>                                         ifTrue: [self apply: #token withArgs: {'|'}.
>                                                 self
>                                                         many: [self apply: #identifier].
>                                                 self apply: #token withArgs: {'|'}]]. [self apply: #empty]}.
>                         self ometaOr: {[true
>                                         ifTrue: [self apply: #expr.
>                                                 self
>                                                         many: [true
>                                                                         ifTrue: [self apply: #token withArgs: {'.'}.
>                                                                                 self apply: #expr]].
>                                                 self ometaOr: {[true
>                                                                 ifTrue: [self apply: #token withArgs: {'.'}.
>                                                                         self apply: #token withArgs: {'^'}.
>                                                                         self apply: #expr]]. [self apply: #empty]}]]. [true
>                                         ifTrue: [self apply: #token withArgs: {'^'}.
>                                                 self apply: #expr]]. [self apply: #empty]}.
>                         self ometaOr: {[self apply: #token withArgs: {'.'}]. [self apply: #empty]}.
>                         self apply: #token withArgs: {']'}]!
>
> ----- Method: O2SqueakRecognizer>>cascade (in category 'rules-parsing') -----
> cascade
>         ^ self ometaOr: {[self apply: #identifier]. [self apply: #binaryMsg]. [self apply: #keywordMsg]}!
>
> ----- Method: O2SqueakRecognizer>>expr (in category 'rules-parsing') -----
> expr
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #identifier.
>                                 self ometaOr: {[self apply: #token withArgs: {':='}]. [self apply: #token withArgs: {'_'}]}.
>                                 self apply: #expr]]. [self apply: #msgExpr]}!
>
> ----- Method: O2SqueakRecognizer>>identifier (in category 'rules-parsing') -----
> identifier
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self apply: #tsIdentifier.
>                         self
>                                 not: [self apply: #exactly withArgs: {$:}]]!
>
> ----- Method: O2SqueakRecognizer>>keyword (in category 'rules-parsing') -----
> keyword
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self apply: #tsKeyword]!
>
> ----- Method: O2SqueakRecognizer>>keywordExpr (in category 'rules-parsing') -----
> keywordExpr
>         ^ true
>                 ifTrue: [self apply: #binaryExpr.
>                         self apply: #keywordMsg]!
>
> ----- Method: O2SqueakRecognizer>>keywordMsg (in category 'rules-parsing') -----
> keywordMsg
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #keywordMsg.
>                                 self apply: #keywordMsgPart]]. [self apply: #keywordMsgPart]}!
>
> ----- Method: O2SqueakRecognizer>>keywordMsgPart (in category 'rules-parsing') -----
> keywordMsgPart
>         ^ true
>                 ifTrue: [self apply: #keyword.
>                         self apply: #binaryExpr]!
>
> ----- Method: O2SqueakRecognizer>>literal (in category 'rules-parsing') -----
> literal
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self ometaOr: {[self apply: #tsNumber]. [self apply: #tsCharacter]. [self apply: #tsString]. [self apply: #tsSymbol]}]!
>
> ----- Method: O2SqueakRecognizer>>msgExpr (in category 'rules-parsing') -----
> msgExpr
>         ^ true
>                 ifTrue: [self ometaOr: {[self apply: #keywordExpr]. [self apply: #binaryExpr]}.
>                         self
>                                 many: [true
>                                                 ifTrue: [self apply: #token withArgs: {';'}.
>                                                         self apply: #cascade]]]!
>
> ----- Method: O2SqueakRecognizer>>squeakExpr (in category 'rules-parsing') -----
> squeakExpr
>         ^ self
>                 consumedBy: [self apply: #expr]!
>
> ----- Method: O2SqueakRecognizer>>symbol (in category 'rules-parsing') -----
> symbol
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {'#'}.
>                         self apply: #spaces.
>                         self ometaOr: {[self apply: #tsString]. [true
>                                         ifTrue: [self apply: #tsKeyword.
>                                                 self ometaOr: {[self apply: #tsIdentifier]. [self apply: #empty]}]]}]!
>
> ----- Method: O2SqueakRecognizer>>tcBinaryChar (in category 'rules-lexing') -----
> tcBinaryChar
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #char.
>                         self pred: (TypeTable at: t1 asciiValue)
>                                         == #xBinary]!
>
> ----- Method: O2SqueakRecognizer>>tsArraySymbol (in category 'rules-lexing') -----
> tsArraySymbol
>         ^ self ometaOr: {[true
>                         ifTrue: [self
>                                         many1: [self apply: #tsKeyword].
>                                 self ometaOr: {[self apply: #tsIdentifier]. [self apply: #empty]}]]. [self apply: #tsIdentifier]}!
>
> ----- Method: O2SqueakRecognizer>>tsBinary (in category 'rules-lexing') -----
> tsBinary
>         ^ true
>                 ifTrue: [self ometaOr: {[self apply: #exactly withArgs: {$|}]. [self apply: #tcBinaryChar]}.
>                         self
>                                 many: [self apply: #tcBinaryChar]]!
>
> ----- Method: O2SqueakRecognizer>>tsCharacter (in category 'rules-lexing') -----
> tsCharacter
>         ^ true
>                 ifTrue: [self apply: #exactly withArgs: {$$}.
>                         self apply: #char]!
>
> ----- Method: O2SqueakRecognizer>>tsIdentifier (in category 'rules-lexing') -----
> tsIdentifier
>         ^ true
>                 ifTrue: [self apply: #letter.
>                         self
>                                 many: [self ometaOr: {[self apply: #letter]. [self apply: #digit]}]]!
>
> ----- Method: O2SqueakRecognizer>>tsKeyword (in category 'rules-lexing') -----
> tsKeyword
>         ^ true
>                 ifTrue: [self apply: #tsIdentifier.
>                         self apply: #exactly withArgs: {$:}]!
>
> ----- Method: O2SqueakRecognizer>>tsNatural (in category 'rules-lexing') -----
> tsNatural
>         ^ self
>                 many1: [self apply: #digit]!
>
> ----- Method: O2SqueakRecognizer>>tsNumber (in category 'rules-lexing') -----
> tsNumber
>         ^ true
>                 ifTrue: [self ometaOr: {[self apply: #exactly withArgs: {$+}]. [self apply: #exactly withArgs: {$-}]. [self apply: #empty]}.
>                         self apply: #tsNatural]!
>
> ----- Method: O2SqueakRecognizer>>tsString (in category 'rules-lexing') -----
> tsString
>         ^ true
>                 ifTrue: [self apply: #exactly withArgs: {$'}.
>                         self
>                                 many: [self ometaOr: {[true
>                                                         ifTrue: [self apply: #exactly withArgs: {$'}.
>                                                                 self apply: #exactly withArgs: {$'}]]. [true
>                                                         ifTrue: [self
>                                                                         not: [self apply: #exactly withArgs: {$'}].
>                                                                 self apply: #char]]}].
>                         self apply: #exactly withArgs: {$'}]!
>
> ----- Method: O2SqueakRecognizer>>tsSymbol (in category 'rules-lexing') -----
> tsSymbol
>         ^ true
>                 ifTrue: [self apply: #exactly withArgs: {$#}.
>                         self apply: #spaces.
>                         self ometaOr: {[self apply: #tsString]. [self apply: #tsArraySymbol]}]!
>
> ----- Method: O2SqueakRecognizer>>unaryExpr (in category 'rules-parsing') -----
> unaryExpr
>         ^ true
>                 ifTrue: [self apply: #unit.
>                         self
>                                 many: [self apply: #identifier]]!
>
> ----- Method: O2SqueakRecognizer>>unit (in category 'rules-parsing') -----
> unit
>         ^ self ometaOr: {[self apply: #literal]. [self apply: #identifier]. [self apply: #arrayLit]. [self apply: #arrayConstr]. [self apply: #block]. [true
>                         ifTrue: [self apply: #token withArgs: {'('}.
>                                 self apply: #expr.
>                                 self apply: #token withArgs: {')'}]]}!
>
> ----- Method: OMeta2>>char (in category 'rules') -----
> char
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self pred: t1 isCharacter.
>                         t1]!
>
> ----- Method: OMeta2>>digit (in category 'rules') -----
> digit
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #char.
>                         self pred: t1 isDigit.
>                         t1]!
>
> ----- Method: OMeta2>>end (in category 'rules') -----
> end
>         ^ self
>                 not: [self apply: #anything]!
>
> ----- Method: OMeta2>>exactly (in category 'rules-meta') -----
> exactly
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t2 := self apply: #anything.
>                         t1 := self apply: #anything.
>                         self pred: t2 = t1.
>                         t2]!
>
> ----- Method: OMeta2>>fromTo (in category 'rules') -----
> fromTo
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         t2 := self apply: #anything.
>                         self apply: #seq withArgs: {t1}.
>                         self
>                                 many: [true
>                                                 ifTrue: [self
>                                                                 not: [self apply: #seq withArgs: {t2}].
>                                                         self apply: #char]].
>                         self apply: #seq withArgs: {t2}]!
>
> ----- Method: OMeta2>>letter (in category 'rules') -----
> letter
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #char.
>                         self pred: t1 isLetter.
>                         t1]!
>
> ----- Method: OMeta2>>letterOrDigit (in category 'rules') -----
> letterOrDigit
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #char.
>                         self pred: t1 isAlphaNumeric.
>                         t1]!
>
> ----- Method: OMeta2>>listOf (in category 'rules-meta') -----
> listOf
>         | t1 t2 t3 t5 |
>         ^ true
>                 ifTrue: [t2 := self apply: #anything.
>                         t1 := self apply: #anything.
>                         self ometaOr: {[true
>                                         ifTrue: [t3 := self apply: #apply withArgs: {t2}.
>                                                 t5 := self
>                                                                         many: [true
>                                                                                         ifTrue: [self apply: #token withArgs: {t1}.
>                                                                                                 self apply: #apply withArgs: {t2}]].
>                                                 t5 addFirst: t3;
>                                                          yourself]]. [true
>                                         ifTrue: [self apply: #empty.
>                                                 #()]]}]!
>
> ----- Method: OMeta2>>lower (in category 'rules') -----
> lower
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #char.
>                         self pred: t1 isLowercase.
>                         t1]!
>
> ----- Method: OMeta2>>notLast (in category 'rules-meta') -----
> notLast
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t2 := self apply: #anything.
>                         t1 := self apply: #apply withArgs: {t2}.
>                         self
>                                 lookahead: [self apply: #apply withArgs: {t2}].
>                         t1]!
>
> ----- Method: OMeta2>>number (in category 'rules') -----
> number
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self pred: t1 isNumber.
>                         t1]!
>
> ----- Method: OMeta2>>range (in category 'rules-meta') -----
> range
>         | t1 t2 t3 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         t2 := self apply: #anything.
>                         t3 := self apply: #anything.
>                         self pred: t1 <= t3 & (t3 <= t2).
>                         t3]!
>
> ----- Method: OMeta2>>space (in category 'rules') -----
> space
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #char.
>                         self pred: t1 asciiValue <= 32.
>                         t1]!
>
> ----- Method: OMeta2>>spaces (in category 'rules') -----
> spaces
>         ^ self
>                 many: [self apply: #space]!
>
> ----- Method: OMeta2>>string (in category 'rules') -----
> string
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self pred: t1 isString.
>                         t1]!
>
> ----- Method: OMeta2>>symbol (in category 'rules') -----
> symbol
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self pred: t1 isSymbol.
>                         t1]!
>
> ----- Method: OMeta2>>token (in category 'rules-meta') -----
> token
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self apply: #spaces.
>                         self apply: #seq withArgs: {t1}]!
>
> ----- Method: OMeta2>>upper (in category 'rules') -----
> upper
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #char.
>                         self pred: t1 isUppercase.
>                         t1]!
>
> OMeta2 subclass: #OMeta2Examples
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> !OMeta2Examples commentStamp: '<historical>' prior: 0!
> Here's how to run these examples:
>
>         OMeta2Examples match: 5 with: #fact.
>         OMeta2Examples matchAll: '1234' with: #number.
>         OMeta2Examples matchAll: 'abc123' with: #identifier.
>         OMeta2Examples matchAll: #($a $b $c 1 2 3 #(4 5)) with: #structure.
>         OMeta2Examples matchAll: 'howdy' with: #greeting.!
>
> ----- Method: OMeta2Examples>>aSqueakMethod (in category 'squeak methods') -----
> aSqueakMethod
>
>         self inform: 'hello world'!
>
> ----- Method: OMeta2Examples>>anotherSqueakMethod (in category 'squeak methods') -----
> anotherSqueakMethod
>
>         self inform: 'good-bye world'!
>
> ----- Method: OMeta2Examples>>digit (in category 'rules') -----
> digit
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self
>                                                 super: OMeta2
>                                                 apply: #digit
>                                                 withArgs: {}.
>                         t1 digitValue]!
>
> ----- Method: OMeta2Examples>>fact (in category 'rules') -----
> fact
>         | t1 t3 |
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #exactly withArgs: {0}.
>                                 1]]. [true
>                         ifTrue: [t3 := self apply: #anything.
>                                 t1 := self apply: #fact withArgs: {t3 - 1}.
>                                 t3 * t1]]}!
>
> ----- Method: OMeta2Examples>>formTest (in category 'rules') -----
> formTest
>         ^ self ometaOr: {[self
>                         form: [true
>                                         ifTrue: [self inform: input hash printString.
>                                                 self apply: #exactly withArgs: {#foo}.
>                                                 self apply: #exactly withArgs: {#bar}]]]. [self
>                         form: [true
>                                         ifTrue: [self inform: input hash printString.
>                                                 self apply: #exactly withArgs: {#bar}]]]}!
>
> ----- Method: OMeta2Examples>>greeting (in category 'rules') -----
> greeting
>         ^ self
>                 consumedBy: [true
>                                 ifTrue: [self apply: #seq withArgs: {'howdy'}.
>                                         self
>                                                 opt: [self apply: #seq withArgs: {'-ho'}]]]!
>
> ----- Method: OMeta2Examples>>identifier (in category 'rules') -----
> identifier
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self
>                                 consumedBy: [true
>                                                 ifTrue: [self apply: #letter.
>                                                         self
>                                                                 many: [self ometaOr: {[self apply: #letter]. [self apply: #digit]}]]]]!
>
> ----- Method: OMeta2Examples>>identifierIdx (in category 'rules') -----
> identifierIdx
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self
>                                 indexConsumedBy: [true
>                                                 ifTrue: [self apply: #letter.
>                                                         self
>                                                                 many: [self ometaOr: {[self apply: #letter]. [self apply: #digit]}]]]]!
>
> ----- Method: OMeta2Examples>>identifiers (in category 'rules') -----
> identifiers
>         ^ self
>                 many: [true
>                                 ifTrue: [self inform: self pos printString.
>                                         self apply: #identifier]]!
>
> ----- Method: OMeta2Examples>>number (in category 'rules') -----
> number
>         | t1 t3 |
>         ^ self ometaOr: {[true
>                         ifTrue: [t3 := self apply: #number.
>                                 t1 := self apply: #digit.
>                                 t3 * 10 + t1]]. [self apply: #digit]}!
>
> ----- Method: OMeta2Examples>>structure (in category 'rules') -----
> structure
>         ^ true
>                 ifTrue: [self apply: #exactly withArgs: {$a}.
>                         self apply: #exactly withArgs: {$b}.
>                         self apply: #exactly withArgs: {$c}.
>                         self apply: #exactly withArgs: {1}.
>                         self apply: #exactly withArgs: {2}.
>                         self apply: #exactly withArgs: {3}.
>                         self
>                                 form: [self
>                                                 many: [self apply: #anything]]]!
>
> OMeta2 subclass: #OMeta2Flattener
>         instanceVariableNames: 'ws'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OMeta2Flattener>>flatten (in category 'rules') -----
> flatten
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self apply: #iFlatten withArgs: {t1}.
>                         ws contents]!
>
> ----- Method: OMeta2Flattener>>iFlatten (in category 'rules') -----
> iFlatten
>         | t1 |
>         ^ self ometaOr: {[true
>                         ifTrue: [t1 := self apply: #string.
>                                 ws nextPutAll: t1]]. [self
>                         form: [self
>                                         many: [self apply: #iFlatten]]]}!
>
> ----- Method: OMeta2Flattener>>initialize (in category 'initialize-release') -----
> initialize
>
>         super initialize.
>         ws := (String new: 64) writeStream!
>
> OMeta2 subclass: #OMeta2NullOpt
>         instanceVariableNames: 'didSomething'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> OMeta2NullOpt subclass: #OMeta2AndOrOpt
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OMeta2AndOrOpt>>and (in category 'rules') -----
> and
>         | t1 t3 |
>         ^ self ometaOr: {[true
>                         ifTrue: [t1 := self apply: #trans.
>                                 self apply: #end.
>                                 self apply: #setHelped.
>                                 t1]]. [true
>                         ifTrue: [t3 := self apply: #transInside withArgs: {#And}.
>                                 t3 addFirst: #And;
>                                          yourself]]}!
>
> ----- Method: OMeta2AndOrOpt>>or (in category 'rules') -----
> or
>         | t1 t3 |
>         ^ self ometaOr: {[true
>                         ifTrue: [t1 := self apply: #trans.
>                                 self apply: #end.
>                                 self apply: #setHelped.
>                                 t1]]. [true
>                         ifTrue: [t3 := self apply: #transInside withArgs: {#Or}.
>                                 t3 addFirst: #Or;
>                                          yourself]]}!
>
> ----- Method: OMeta2AndOrOpt>>transInside (in category 'rules') -----
> transInside
>         | t1 t2 t4 t5 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self ometaOr: {[true
>                                         ifTrue: [self
>                                                         form: [true
>                                                                         ifTrue: [self apply: #exactly withArgs: {t1}.
>                                                                                 t4 := self apply: #transInside withArgs: {t1}]].
>                                                 t5 := self apply: #transInside withArgs: {t1}.
>                                                 self apply: #setHelped.
>                                                 t4 , t5]]. [true
>                                         ifTrue: [t2 := self apply: #trans.
>                                                 t4 := self apply: #transInside withArgs: {t1}.
>                                                 t4 addFirst: t2;
>                                                          yourself]]. [true
>                                         ifTrue: [self apply: #empty.
>                                                 OrderedCollection new]]}]!
>
> ----- Method: OMeta2NullOpt>>and (in category 'rules') -----
> and
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self
>                                                 many: [self apply: #trans].
>                         t1 addFirst: #And;
>                                  yourself]!
>
> ----- Method: OMeta2NullOpt>>consby (in category 'rules') -----
> consby
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#ConsBy. t1}]!
>
> ----- Method: OMeta2NullOpt>>form (in category 'rules') -----
> form
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#Form. t1}]!
>
> ----- Method: OMeta2NullOpt>>helped (in category 'rules') -----
> helped
>         ^ self pred: didSomething!
>
> ----- Method: OMeta2NullOpt>>idxconsby (in category 'rules') -----
> idxconsby
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#IdxConsBy. t1}]!
>
> ----- Method: OMeta2NullOpt>>initialize (in category 'initialize-release') -----
> initialize
>
>         super initialize.
>         didSomething := false!
>
> ----- Method: OMeta2NullOpt>>lookahead (in category 'rules') -----
> lookahead
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#Lookahead. t1}]!
>
> ----- Method: OMeta2NullOpt>>many (in category 'rules') -----
> many
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#Many. t1}]!
>
> ----- Method: OMeta2NullOpt>>many1 (in category 'rules') -----
> many1
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#Many1. t1}]!
>
> ----- Method: OMeta2NullOpt>>not (in category 'rules') -----
> not
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#Not. t1}]!
>
> ----- Method: OMeta2NullOpt>>opt (in category 'rules') -----
> opt
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {#Opt. t1}]!
>
> ----- Method: OMeta2NullOpt>>optimize (in category 'rules') -----
> optimize
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         self apply: #helped.
>                         t1]!
>
> ----- Method: OMeta2NullOpt>>or (in category 'rules') -----
> or
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self
>                                                 many: [self apply: #trans].
>                         t1 addFirst: #Or;
>                                  yourself]!
>
> ----- Method: OMeta2NullOpt>>rule (in category 'rules') -----
> rule
>         | t1 t2 t3 |
>         ^ true
>                 ifTrue: [t2 := self apply: #anything.
>                         t3 := self apply: #anything.
>                         t1 := self apply: #trans.
>                         {#Rule. t2. t3. t1}]!
>
> ----- Method: OMeta2NullOpt>>set (in category 'rules') -----
> set
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         t2 := self apply: #trans.
>                         {#Set. t1. t2}]!
>
> ----- Method: OMeta2NullOpt>>setHelped (in category 'rules') -----
> setHelped
>         ^ didSomething := true!
>
> ----- Method: OMeta2NullOpt>>trans (in category 'rules') -----
> trans
>         | t1 t3 |
>         ^ self ometaOr: {[true
>                         ifTrue: [self
>                                         form: [true
>                                                         ifTrue: [t3 := self apply: #anything.
>                                                                 t3 := t3 asLowercase asSymbol.
>                                                                 self
>                                                                         pred: (self class canUnderstand: t3).
>                                                                 t1 := self apply: #apply withArgs: {t3}]].
>                                 t1]]. [self apply: #anything]}!
>
> OMeta2 subclass: #OMeta2Optimizer
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OMeta2Optimizer>>optimizeRule (in category 'rules') -----
> optimizeRule
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self
>                                 many: [t1 := self apply: #foreign withArgs: {OMeta2AndOrOpt. #optimize. t1}].
>                         t1]!
>
> OMeta2 subclass: #OMeta2RuleParser
>         instanceVariableNames: 'temps'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OMeta2RuleParser class>>isOMeta2Rule: (in category 'as yet unclassified') -----
> isOMeta2Rule: aString
>
>         ^ [(self matchAll: aString with: #rule) first ~= #Squeak] on: OM2Fail do: [false]!
>
> ----- Method: OMeta2RuleParser>>application (in category 'rules') -----
> application
>         | t1 t3 t4 |
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #token withArgs: {'^'}.
>                                 t4 := self apply: #name.
>                                 t1 := self apply: #args.
>                                 {#SuperApp. t4} , t1]]. [true
>                         ifTrue: [t3 := self apply: #name.
>                                 self apply: #exactly withArgs: {$.}.
>                                 t4 := self apply: #nsName.
>                                 t1 := self apply: #args.
>                                 {#App. #foreign. t3. ('#' , t4) asSymbol} , t1]]. [true
>                         ifTrue: [t4 := self apply: #name.
>                                 t1 := self apply: #args.
>                                 {#App. t4} , t1]]}!
>
> ----- Method: OMeta2RuleParser>>args (in category 'rules') -----
> args
>         | t1 |
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #exactly withArgs: {$(}.
>                                 t1 := self apply: #listOf withArgs: {#squeakExpression. '.'}.
>                                 self apply: #token withArgs: {')'}.
>                                 t1]]. [true
>                         ifTrue: [self
>                                         not: [self apply: #exactly withArgs: {$(}].
>                                 #()]]}!
>
> ----- Method: OMeta2RuleParser>>characterLiteral (in category 'rules') -----
> characterLiteral
>         | t1 |
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self apply: #exactly withArgs: {$$}.
>                         t1 := self apply: #char.
>                         {#App. #exactly. t1 storeString}]!
>
> ----- Method: OMeta2RuleParser>>characters (in category 'rules') -----
> characters
>         | t1 |
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {'``'}.
>                         t1 := self
>                                                 many: [true
>                                                                 ifTrue: [self
>                                                                                 not: [true
>                                                                                                 ifTrue: [self apply: #exactly withArgs: {$'}.
>                                                                                                         self apply: #exactly withArgs: {$'}]].
>                                                                         self apply: #char]].
>                         self apply: #exactly withArgs: {$'}.
>                         self apply: #exactly withArgs: {$'}.
>                         {#App. #seq. (String withAll: t1) storeString}]!
>
> ----- Method: OMeta2RuleParser>>expr (in category 'rules') -----
> expr
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #listOf withArgs: {#expr4. '|'}.
>                         (OrderedCollection with: #Or) addAll: t1;
>                                  yourself]!
>
> ----- Method: OMeta2RuleParser>>expr1 (in category 'rules') -----
> expr1
>         | t1 t3 |
>         ^ self ometaOr: {[true
>                         ifTrue: [t3 := self ometaOr: {[self apply: #keyword withArgs: {'true'}]. [self apply: #keyword withArgs: {'false'}]. [self apply: #keyword withArgs: {'nil'}]}.
>                                 {#App. #exactly. t3}]]. [self apply: #application]. [self apply: #semanticAction]. [self apply: #semanticPredicate]. [self apply: #characters]. [self apply: #tokenSugar]. [self apply: #stringLiteral]. [self apply: #symbolLiteral]. [self apply: #numberLiteral]. [self apply: #characterLiteral]. [true
>                         ifTrue: [self apply: #token withArgs: {'{'}.
>                                 t1 := self apply: #expr.
>                                 self apply: #token withArgs: {'}'}.
>                                 {#Form. t1}]]. [true
>                         ifTrue: [self apply: #token withArgs: {'<'}.
>                                 t1 := self apply: #expr.
>                                 self apply: #token withArgs: {'>'}.
>                                 {#ConsBy. t1}]]. [true
>                         ifTrue: [self apply: #token withArgs: {'@<'}.
>                                 t1 := self apply: #expr.
>                                 self apply: #token withArgs: {'>'}.
>                                 {#IdxConsBy. t1}]]. [true
>                         ifTrue: [self apply: #token withArgs: {'('}.
>                                 t1 := self apply: #expr.
>                                 self apply: #token withArgs: {')'}.
>                                 t1]]}!
>
> ----- Method: OMeta2RuleParser>>expr2 (in category 'rules') -----
> expr2
>         | t1 |
>         ^ self ometaOr: {[true
>                         ifTrue: [self apply: #token withArgs: {'~'}.
>                                 t1 := self apply: #expr2.
>                                 {#Not. t1}]]. [true
>                         ifTrue: [self apply: #token withArgs: {'&'}.
>                                 t1 := self apply: #expr2.
>                                 {#Lookahead. t1}]]. [self apply: #expr1]}!
>
> ----- Method: OMeta2RuleParser>>expr3 (in category 'rules') -----
> expr3
>         | t1 t3 |
>         ^ self ometaOr: {[true
>                         ifTrue: [t3 := self apply: #expr2.
>                                 t3 := self apply: #optIter withArgs: {t3}.
>                                 self ometaOr: {[true
>                                                 ifTrue: [self apply: #exactly withArgs: {$:}.
>                                                         t1 := self apply: #nsName.
>                                                         temps add: t1.
>                                                         {#Set. t1. t3}]]. [true
>                                                 ifTrue: [self apply: #empty.
>                                                         t3]]}]]. [true
>                         ifTrue: [self apply: #token withArgs: {':'}.
>                                 t1 := self apply: #nsName.
>                                 temps add: t1.
>                                 {#Set. t1. {#App. #anything}}]]}!
>
> ----- Method: OMeta2RuleParser>>expr4 (in category 'rules') -----
> expr4
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self
>                                                 many: [self apply: #expr3].
>                         (OrderedCollection with: #And) addAll: t1;
>                                  yourself]!
>
> ----- Method: OMeta2RuleParser>>initialize (in category 'initialize-release') -----
> initialize
>
>         super initialize.
>         temps := IdentitySet new!
>
> ----- Method: OMeta2RuleParser>>keyword (in category 'rules-meta') -----
> keyword
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self apply: #token withArgs: {t1}.
>                         self
>                                 not: [self apply: #letterOrDigit].
>                         t1]!
>
> ----- Method: OMeta2RuleParser>>name (in category 'rules') -----
> name
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         self apply: #nsName]!
>
> ----- Method: OMeta2RuleParser>>nameFirst (in category 'rules') -----
> nameFirst
>         ^ self apply: #letter!
>
> ----- Method: OMeta2RuleParser>>nameRest (in category 'rules') -----
> nameRest
>         ^ self ometaOr: {[self apply: #nameFirst]. [self apply: #digit]}!
>
> ----- Method: OMeta2RuleParser>>nsName (in category 'rules') -----
> nsName
>         | t1 |
>         ^ self ometaOr: {[true
>                         ifTrue: [t1 := self apply: #firstAndRest withArgs: {#nameFirst. #nameRest}.
>                                 (String withAll: t1) asSymbol]]. [true
>                         ifTrue: [self apply: #exactly withArgs: {$_}.
>                                 #anything]]}!
>
> ----- Method: OMeta2RuleParser>>numberLiteral (in category 'rules') -----
> numberLiteral
>         | t1 t2 |
>         ^ true
>                 ifTrue: [self apply: #spaces.
>                         t2 := self ometaOr: {[true
>                                                         ifTrue: [self apply: #exactly withArgs: {$-}.
>                                                                 self apply: #spaces.
>                                                                 -1]]. [true
>                                                         ifTrue: [self apply: #empty.
>                                                                 1]]}.
>                         t1 := self
>                                                 many1: [self apply: #digit].
>                         {#App. #exactly. (t2 * (String withAll: t1) asNumber) storeString}]!
>
> ----- Method: OMeta2RuleParser>>optIter (in category 'rules-meta') -----
> optIter
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #anything.
>                         self ometaOr: {[true
>                                         ifTrue: [self apply: #token withArgs: {'*'}.
>                                                 {#Many. t1}]]. [true
>                                         ifTrue: [self apply: #token withArgs: {'+'}.
>                                                 {#Many1. t1}]]. [true
>                                         ifTrue: [self apply: #token withArgs: {'?'}.
>                                                 self
>                                                         not: [self apply: #exactly withArgs: {$[}].
>                                                 {#Opt. t1}]]. [true
>                                         ifTrue: [self apply: #empty.
>                                                 t1]]}]!
>
> ----- Method: OMeta2RuleParser>>rule (in category 'rules') -----
> rule
>         | t1 t3 t4 t5 |
>         ^ self ometaOr: {[true
>                         ifTrue: [self
>                                         not: [true
>                                                         ifTrue: [self
>                                                                         many: [self
>                                                                                         super: OMeta2
>                                                                                         apply: #space
>                                                                                         withArgs: {}].
>                                                                 self apply: #nsName.
>                                                                 self apply: #expr4.
>                                                                 self apply: #token withArgs: {'='}]].
>                                 t3 := self
>                                                         consumedBy: [self
>                                                                         many: [self apply: #char]].
>                                 {#Squeak. t3}]]. [true
>                         ifTrue: [t1 := self
>                                                         lookahead: [true
>                                                                         ifTrue: [self
>                                                                                         many: [self
>                                                                                                         super: OMeta2
>                                                                                                         apply: #space
>                                                                                                         withArgs: {}].
>                                                                                 self apply: #nsName]].
>                                 t4 := self apply: #rulePart withArgs: {t1}.
>                                 t5 := self
>                                                         many: [true
>                                                                         ifTrue: [self apply: #token withArgs: {','}.
>                                                                                 self apply: #rulePart withArgs: {t1}]].
>                                 self apply: #spaces.
>                                 self apply: #end.
>                                 {#Rule. t1. temps asSortedCollection. (OrderedCollection with: #Or with: t4) addAll: t5;
>                                          yourself}]]}!
>
> ----- Method: OMeta2RuleParser>>rulePart (in category 'rules-meta') -----
> rulePart
>         | t1 t2 t3 t4 |
>         ^ true
>                 ifTrue: [t3 := self apply: #anything.
>                         t2 := self apply: #name.
>                         self pred: t2 = t3.
>                         t1 := self apply: #expr4.
>                         self ometaOr: {[true
>                                         ifTrue: [self apply: #token withArgs: {'='}.
>                                                 t4 := self apply: #expr.
>                                                 {#And. t1. t4}]]. [true
>                                         ifTrue: [self apply: #empty.
>                                                 t1]]}]!
>
> ----- Method: OMeta2RuleParser>>semanticAction (in category 'rules') -----
> semanticAction
>         | t1 |
>         ^ true
>                 ifTrue: [self
>                                 opt: [self apply: #token withArgs: {'->'}].
>                         self apply: #token withArgs: {'['}.
>                         t1 := self apply: #squeakExpression.
>                         self apply: #exactly withArgs: {$]}.
>                         {#Act. t1}]!
>
> ----- Method: OMeta2RuleParser>>semanticPredicate (in category 'rules') -----
> semanticPredicate
>         | t1 |
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {'?['}.
>                         t1 := self apply: #squeakExpression.
>                         self apply: #exactly withArgs: {$]}.
>                         {#Pred. t1}]!
>
> ----- Method: OMeta2RuleParser>>space (in category 'rules') -----
> space
>         ^ self ometaOr: {[self
>                         super: OMeta2
>                         apply: #space
>                         withArgs: {}]. [self apply: #fromTo withArgs: {'/*'. '*/'}]. [self apply: #fromTo withArgs: {'//'. String cr}]}!
>
> ----- Method: OMeta2RuleParser>>squeakExpression (in category 'rules') -----
> squeakExpression
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #foreign withArgs: {O2SqueakRecognizer. #squeakExpr}.
>                         self apply: #spaces.
>                         t1]!
>
> ----- Method: OMeta2RuleParser>>stringLiteral (in category 'rules') -----
> stringLiteral
>         | t1 |
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {''''}.
>                         t1 := self
>                                                 many: [self ometaOr: {[true
>                                                                         ifTrue: [self apply: #exactly withArgs: {$'}.
>                                                                                 self apply: #exactly withArgs: {$'}.
>                                                                                 $']]. [true
>                                                                         ifTrue: [self
>                                                                                         not: [self apply: #exactly withArgs: {$'}].
>                                                                                 self apply: #char]]}].
>                         self apply: #exactly withArgs: {$'}.
>                         {#App. #exactly. (String withAll: t1) storeString}]!
>
> ----- Method: OMeta2RuleParser>>symbolLiteral (in category 'rules') -----
> symbolLiteral
>         | t1 |
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {'#'}.
>                         t1 := self apply: #nsName.
>                         {#App. #exactly. t1 storeString}]!
>
> ----- Method: OMeta2RuleParser>>tokenSugar (in category 'rules') -----
> tokenSugar
>         | t1 |
>         ^ true
>                 ifTrue: [self apply: #token withArgs: {'"'}.
>                         t1 := self
>                                                 many: [true
>                                                                 ifTrue: [self
>                                                                                 not: [self apply: #exactly withArgs: {$"}].
>                                                                         self apply: #char]].
>                         self apply: #exactly withArgs: {$"}.
>                         {#App. #token. (String withAll: t1) storeString}]!
>
> OMeta2 subclass: #OMeta2RuleTranslator
>         instanceVariableNames: 'grammarClass'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OMeta2RuleTranslator>>act (in category 'rules') -----
> act
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #string.
>                         {'('. t1. ')'}]!
>
> ----- Method: OMeta2RuleTranslator>>and (in category 'rules') -----
> and
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self
>                                                 many: [self apply: #trans].
>                         {'(true ifTrue: ['. self delim: t1 with: '. '. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>app (in category 'rules') -----
> app
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t1 := self apply: #symbol.
>                         self ometaOr: {[true
>                                         ifTrue: [t2 := self
>                                                                         many1: [self apply: #anything].
>                                                 t2 := self delim: t2 with: '. '.
>                                                 {'(self apply: '. t1 storeString. ' withArgs: {'. t2. '})'}]]. [{'(self apply: '. t1 storeString. ')'}]}]!
>
> ----- Method: OMeta2RuleTranslator>>consby (in category 'rules') -----
> consby
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self consumedBy: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>delim:with: (in category 'helpers') -----
> delim: aSequenceableCollection  with: anObject
>
>         | first ans |
>         first := true.
>         ans := OrderedCollection new.
>         aSequenceableCollection do: [:x |
>                 first ifTrue: [first := false] ifFalse: [ans add: anObject].
>                 ans add: x
>         ].
>         ^ ans!
>
> ----- Method: OMeta2RuleTranslator>>form (in category 'rules') -----
> form
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self form: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>idxconsby (in category 'rules') -----
> idxconsby
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self indexConsumedBy: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>lookahead (in category 'rules') -----
> lookahead
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self lookahead: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>many (in category 'rules') -----
> many
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self many: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>many1 (in category 'rules') -----
> many1
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self many1: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>not (in category 'rules') -----
> not
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self not: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>opt (in category 'rules') -----
> opt
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #trans.
>                         {'(self opt: ['. t1. '])'}]!
>
> ----- Method: OMeta2RuleTranslator>>or (in category 'rules') -----
> or
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t1 := self
>                                                 many: [true
>                                                                 ifTrue: [t2 := self apply: #trans.
>                                                                         {'['. t2. ']'}]].
>                         {'(self ometaOr: {'. self delim: t1 with: '. '. '})'}]!
>
> ----- Method: OMeta2RuleTranslator>>pred (in category 'rules') -----
> pred
>         | t1 |
>         ^ true
>                 ifTrue: [t1 := self apply: #string.
>                         {'(self pred: ('. t1. '))'}]!
>
> ----- Method: OMeta2RuleTranslator>>rule (in category 'rules') -----
> rule
>         | t1 t2 t3 |
>         ^ true
>                 ifTrue: [t2 := self apply: #symbol.
>                         t3 := self apply: #anything.
>                         t3 := t3
>                                                 select: [:t4 | (grammarClass instVarNames includes: t4) not].
>                         t1 := self apply: #trans.
>                         {t2. ' |'. self delim: t3 asSortedCollection with: ' '. ' | ^ '. t1}]!
>
> ----- Method: OMeta2RuleTranslator>>set (in category 'rules') -----
> set
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t1 := self apply: #symbol.
>                         t2 := self apply: #trans.
>                         {'('. t1 asString. ' := '. t2. ')'}]!
>
> ----- Method: OMeta2RuleTranslator>>squeak (in category 'rules') -----
> squeak
>         ^ self apply: #string!
>
> ----- Method: OMeta2RuleTranslator>>superapp (in category 'rules') -----
> superapp
>         | t1 t2 |
>         ^ true
>                 ifTrue: [t2 := self apply: #symbol.
>                         t1 := self
>                                                 many: [self apply: #anything].
>                         t1 := self delim: t1 with: '. '.
>                         {'(self super: '. grammarClass superclass name. ' apply: '. t2 storeString. ' withArgs: {'. t1. '})'}]!
>
> ----- Method: OMeta2RuleTranslator>>trans (in category 'rules') -----
> trans
>         | t1 t3 |
>         ^ true
>                 ifTrue: [self
>                                 form: [true
>                                                 ifTrue: [t3 := self apply: #symbol.
>                                                         t1 := self apply: #apply withArgs: {t3 asLowercase asSymbol}]].
>                         t1]!
>
> ----- Method: OMeta2RuleTranslator>>translate (in category 'rules') -----
> translate
>         ^ true
>                 ifTrue: [grammarClass := self apply: #anything.
>                         self apply: #trans]!
>
> ----- Method: OMeta2Base class>>compilerClass (in category 'as yet unclassified') -----
> compilerClass
>
>         ^ OMeta2Compiler!
>
> ----- Method: OMeta2Base class>>debugMatch:with: (in category 'as yet unclassified') -----
> debugMatch: anObject with: aRule
>
>         ^ self debugMatch: anObject with: aRule withArgs: #()!
>
> ----- Method: OMeta2Base class>>debugMatch:with:withArgs: (in category 'as yet unclassified') -----
> debugMatch: anObject with: aRule withArgs: args
>
>         ^ self debugMatchAll: {anObject} readStream with: aRule withArgs: args!
>
> ----- Method: OMeta2Base class>>debugMatchAll:with: (in category 'as yet unclassified') -----
> debugMatchAll: aSequenceableCollection with: aRule
>
>         ^ self debugMatchAll: aSequenceableCollection with: aRule withArgs: #()!
>
> ----- Method: OMeta2Base class>>debugMatchAll:with:withArgs: (in category 'as yet unclassified') -----
> debugMatchAll: aSequenceableCollection with: aRule withArgs: args
>
>         ^ self matchStream: aSequenceableCollection readStream with: aRule withArgs: args withPlaybackDebugging: true!
>
> ----- Method: OMeta2Base class>>match:with: (in category 'as yet unclassified') -----
> match: anObject with: aRule
>
>         ^ self match: anObject with: aRule withArgs: #()!
>
> ----- Method: OMeta2Base class>>match:with:withArgs: (in category 'as yet unclassified') -----
> match: anObject with: aRule withArgs: args
>
>         ^ self matchAll: {anObject} readStream with: aRule withArgs: args!
>
> ----- Method: OMeta2Base class>>matchAll:with: (in category 'as yet unclassified') -----
> matchAll: aSequenceableCollection with: aRule
>
>         ^ self matchAll: aSequenceableCollection with: aRule withArgs: #()!
>
> ----- Method: OMeta2Base class>>matchAll:with:withArgs: (in category 'as yet unclassified') -----
> matchAll: aSequenceableCollection with: aRule withArgs: args
>
>         ^ self matchStream: aSequenceableCollection readStream with: aRule withArgs: args withPlaybackDebugging: false!
>
> ----- Method: OMeta2Base class>>matchStream:with:withArgs:withPlaybackDebugging: (in category 'as yet unclassified') -----
> matchStream: aReadStream with: aRule withArgs: args withPlaybackDebugging: debugging
>
>         | input matcher ans|
>         input := OM2LazyStream for: aReadStream withPos: 1.
>         matcher := self new initInput: input.
>         [
>                 matcher apply: #empty withArgs: args.
>                 ans := matcher apply: aRule.
>                 matcher apply: #end.
>                 ^ ans
>         ] on: OM2Fail do: [:e |
>                 | curr prev prevPrev |
>                 debugging ifFalse: [e signal].
>                 curr := input.
>                 prev := nil.
>                 prevPrev := nil.
>                 [curr notNil] whileTrue: [
>                         prevPrev := prev.
>                         prev := curr.
>                         curr := curr basicTail
>                 ].
>                 curr := prevPrev ifNotNil: [prevPrev] ifNil: [prev].
>                 self inform: 'will halt each time matcher reaches ', curr printString.
>                 matcher
>                         initInput: input;
>                         forgetEverything.
>                 curr ifNil: [self error: 'you''ve found a bug -- please tell Alex'].
>                 curr become: (OM2StreamDebugger for: curr copy).
>                 matcher haltingPoint: curr.
>                 matcher apply: #empty withArgs: args.
>                 ans := matcher apply: aRule.
>                 matcher apply: #end.
>                 ^ ans
>         ]!
>
> ----- Method: OMeta2Base class>>matcherOn: (in category 'as yet unclassified') -----
> matcherOn: aReadStream
>
>         | input matcher |
>         input := OM2LazyStream for: aReadStream withPos: 1.
>         matcher := self new initInput: input.
>         ^ matcher!
>
> ----- Method: OMeta2Base>>anything (in category 'rules-basic') -----
> anything
>
>         | ans |
>         ans := input head.
>         input := input tail.
>         ^ ans!
>
> ----- Method: OMeta2Base>>apply (in category 'rules-basic') -----
> apply
>
>         | aRule |
>         aRule := self apply: #anything.
>         ^ self apply: aRule!
>
> ----- Method: OMeta2Base>>apply: (in category 'rule application') -----
> apply: aRule
>
>         " A memoRec is an association whose key is the answer,
>           and whose value is the next input. Failers pretend to
>      be memoRecs, but throw a fail in response to #value "
>         | memo memoRec |
>         input == haltingPoint ifTrue: [self halt].
>         memo := input memo.
>         memoRec := memo at: aRule ifAbsent: [nil].
>         memoRec ifNil: [
>                 | origInput failer ans |
>                 origInput := input.
>                 failer := OM2Failer new.
>                 memo at: aRule put: failer.
>                 ans := self perform: aRule.
>                 memoRec := ans -> input.
>                 memo at: aRule put: memoRec.
>                 failer used ifTrue: [
>                         " left recursion detected "
>                         | sentinel keepGoing |
>                         sentinel := input.
>                         keepGoing := true.
>                         [keepGoing] whileTrue: [
>                                 [
>                                         input := origInput.
>                                         ans := self perform: aRule.
>                                         input == sentinel ifTrue: [OMeta2Fail signal].
>                                         memoRec key: ans value: input.
>                                 ] on: OM2Fail do: [keepGoing := false]
>                         ]
>                 ]
>         ].
>         input := memoRec value.
>         ^ memoRec key!
>
> ----- Method: OMeta2Base>>apply:withArgs: (in category 'rule application') -----
> apply: aRule withArgs: args
>
>         args reverseDo: [:a | input := OM2Stream new initHead: a tail: input].
>         ^ self perform: aRule!
>
> ----- Method: OMeta2Base>>consumedBy: (in category 'private') -----
> consumedBy: aBlock
>
>         | origInput i ws |
>         origInput := input.
>         aBlock value.
>         ws := WriteStream on: origInput inputSpecies new.
>         i := origInput.
>         [i == input] whileFalse: [
>                 ws nextPut: i head.
>                 i := i tail
>         ].
>         ^ ws contents!
>
> ----- Method: OMeta2Base>>empty (in category 'rules-basic') -----
> empty
>
>         ^ true!
>
> ----- Method: OMeta2Base>>firstAndRest (in category 'rules-basic') -----
> firstAndRest
>
>         | first rest |
>         first := self apply: #anything.
>         rest := self apply: #anything.
>         ^ self genericMany: [self apply: rest] into: (OrderedCollection with: (self apply: first))!
>
> ----- Method: OMeta2Base>>foreign (in category 'rules-basic') -----
> foreign
>
>         | aGrammar aRule g ans |
>         aGrammar := self apply: #anything.
>         aRule := self apply: #anything.
>         g := aGrammar new initInput: (OM2StreamProxy for: input).
>         ans := g apply: aRule.
>         input := g input target.
>         ^ ans!
>
> ----- Method: OMeta2Base>>forgetEverything (in category 'forgetting') -----
> forgetEverything
>
>         input transitiveForgetEverything.
>         om2streams valuesDo: [:s | s transitiveForgetEverything]!
>
> ----- Method: OMeta2Base>>form: (in category 'rules-basic') -----
> form: aBlock
>
>         | v origInput |
>         v := self apply: #anything.
>         self pred: (v isCollection and: [v isSequenceable and: [v isSymbol not]]).
>         origInput := input.
>         input := om2streams at: v ifAbsentPut: [OM2LazyStream for: v readStream withPos: 1].
>         aBlock value.
>         self apply: #end.
>         input := origInput.
>         ^ v!
>
> ----- Method: OMeta2Base>>genericMany:into: (in category 'private') -----
> genericMany: aBlock into: anOrderedCollection
>
>         [
>                 | origInput |
>                 origInput := input.
>                 [anOrderedCollection addLast: aBlock value] on: OM2Fail do: [
>                         input := origInput.
>                         ^ anOrderedCollection
>                 ].
>                 true
>         ] whileTrue!
>
> ----- Method: OMeta2Base>>haltingPoint: (in category 'initialize-release') -----
> haltingPoint: anOM2Stream
>
>         haltingPoint := anOM2Stream!
>
> ----- Method: OMeta2Base>>indexConsumedBy: (in category 'private') -----
> indexConsumedBy: aBlock
>
>         | from to |
>         from := self pos.
>         aBlock value.
>         to := self pos.
>         ^ from -> to!
>
> ----- Method: OMeta2Base>>initInput: (in category 'initialize-release') -----
> initInput: i
>
>         input := i!
>
> ----- Method: OMeta2Base>>initialize (in category 'initialize-release') -----
> initialize
>
>         super initialize.
>         om2streams := IdentityDictionary new!
>
> ----- Method: OMeta2Base>>input (in category 'rules-basic') -----
> input
>
>         ^ input!
>
> ----- Method: OMeta2Base>>lookahead: (in category 'private') -----
> lookahead: aBlock
>
>         | origInput ans |
>         origInput := input.
>         ans := aBlock value.
>         input := origInput.
>         ^ ans!
>
> ----- Method: OMeta2Base>>many1: (in category 'private') -----
> many1: aBlock
>
>         ^ self genericMany: aBlock into: (OrderedCollection with: aBlock value)!
>
> ----- Method: OMeta2Base>>many: (in category 'private') -----
> many: aBlock
>
>         ^ self genericMany: aBlock into: OrderedCollection new!
>
> ----- Method: OMeta2Base>>not: (in category 'private') -----
> not: aBlock
>
>         | origInput |
>         origInput := input.
>         [aBlock value] on: OM2Fail do: [
>                 input := origInput.
>                 ^ true
>         ].
>         OMeta2Fail signal!
>
> ----- Method: OMeta2Base>>ometaOr: (in category 'private') -----
> ometaOr: choices
>
>         | origInput |
>         origInput := input.
>         choices do: [:choice |
>                 input := origInput.
>                 [^ choice value] on: OM2Fail do: []
>         ].
>         OMeta2Fail signal!
>
> ----- Method: OMeta2Base>>opt: (in category 'private') -----
> opt: aBlock
>
>         ^ self ometaOr: {
>                 [aBlock value].
>                 [nil]
>         }!
>
> ----- Method: OMeta2Base>>pos (in category 'rules-basic') -----
> pos
>
>         ^ input pos!
>
> ----- Method: OMeta2Base>>pred: (in category 'private') -----
> pred: aBooleanValue
>
>         " may want to have the compiler inline this automatically, for performance "
>         aBooleanValue ifTrue: [^ true].
>         OMeta2Fail signal!
>
> ----- Method: OMeta2Base>>seq (in category 'rules-basic') -----
> seq
>
>         | xs |
>         xs := self apply: #anything.
>         xs do: [:x |
>                 " may want to inline #apply:withArgs: below as an
>                   optimization, since this rule gets used a lot "
>                 self apply: #exactly withArgs: {x}
>         ].
>         ^ xs
>         !
>
> ----- Method: OMeta2Base>>super:apply:withArgs: (in category 'rule application') -----
> super: superclass apply: aRule withArgs: args
>
>         args reverseDo: [:a | input := OM2Stream new initHead: a tail: input].
>         ^ self perform: aRule withArguments: #() inSuperclass: superclass!
>
> MethodNode subclass: #OMeta2MethodNode
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'OMeta2'!
>
> ----- Method: OMeta2MethodNode>>schematicTempNamesString (in category 'debugger support') -----
> schematicTempNamesString
>         "The decompiler wants a list of temp names. However, this mechanism depends on a number of assumptions that do not hold with OMeta2 generated methods. Therefore we simply skip the temp names, letting the decompiler build generic ones."
>         ^nil!
>
>



-- 
-- Yoshiki


More information about the Squeak-dev mailing list