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 #xLetter #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 #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 #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! |
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, <[hidden email]> 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 |
Hi,
On 31.07.2014, at 22:34, Yoshiki Ohshima <[hidden email]> wrote: > 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)? The diff is that big becaus OMeta is not in the trunk repository (and hench not in the inbox). Did you mean to commit it to http://www.squeaksource.com/OMeta ? This is also where the config map is. Best -Tobias signature.asc (1K) Download Attachment |
On 31 July 2014 21:37, Tobias Pape <[hidden email]> wrote:
> Hi, > > On 31.07.2014, at 22:34, Yoshiki Ohshima <[hidden email]> wrote: > >> 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)? > > The diff is that big becaus OMeta is not in the trunk repository (and hench > not in the inbox). > Did you mean to commit it to http://www.squeaksource.com/OMeta ? > This is also where the config map is. > > Best > -Tobias Oh, I do like to see OMeta getting some love! That repo (http://www.squeaksource.com/OMeta) has _only "preload" and "postload" packages. Is that right? I'd sort've expected, from the names, that there would be a plain "ometa" package in the middle. frank |
In reply to this post by Yoshiki Ohshima-3
On Thu, Jul 31, 2014 at 10:34 AM, Yoshiki Ohshima <[hidden email]> wrote: Hmm, ok. This diff has more code than it should have, but I patched Hopefully the CompiledMethod>>methodNode override is unnecessary.
... Aloha, Eliot
|
In reply to this post by Frank Shearar-3
On 31.07.2014, at 22:40, Frank Shearar <[hidden email]> wrote: > On 31 July 2014 21:37, Tobias Pape <[hidden email]> wrote: >> Hi, >> >> On 31.07.2014, at 22:34, Yoshiki Ohshima <[hidden email]> wrote: >> >>> 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)? >> >> The diff is that big becaus OMeta is not in the trunk repository (and hench >> not in the inbox). >> Did you mean to commit it to http://www.squeaksource.com/OMeta ? >> This is also where the config map is. >> >> Best >> -Tobias > > Oh, I do like to see OMeta getting some love! > > That repo (http://www.squeaksource.com/OMeta) has _only "preload" and > "postload" packages. Is that right? I'd sort've expected, from the > names, that there would be a plain "ometa" package in the middle. Load the config map, witch says: Load the preload Load the postload. The preload is: “pre-compiled” Ometa in Squeak The postload is: ometa in ometa (compiled on load by the “pre-compiled” ometa version) AND: mark both packages as non-dirty BTW: this is also one of the instances that use non-trivial PackageInfo trickey Best -Tobias signature.asc (1K) Download Attachment |
In reply to this post by Eliot Miranda-2
Ah, yes. It works with your version of CompiledMethod>>methodNode at
5/17/2014 17:56. On Thu, Jul 31, 2014 at 1:41 PM, Eliot Miranda <[hidden email]> wrote: > > > > On Thu, Jul 31, 2014 at 10:34 AM, Yoshiki Ohshima <[hidden email]> > wrote: >> >> 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)? > > > Hopefully the CompiledMethod>>methodNode override is unnecessary. > > >> >> On Thu, Jul 31, 2014 at 1:31 PM, <[hidden email]> 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'! >> > > > > ... > > -- > Aloha, > Eliot > > > -- -- Yoshiki |
In reply to this post by Tobias Pape
Hm. If I do the naive thing, and run
Installer squeaksource project: 'OMeta'; install: 'OMeta2'. I get a DNU in OMeta2Compiler>>#compile:in:notifying:ifFail: that self doesn't understand #from:class:context:notifying:. Is this maybe behind Yoshiki's commit? (Also, if there are any tests, and you have a handy script, I can try get a build up & running for OMeta.) frank On 31 July 2014 21:43, Tobias Pape <[hidden email]> wrote: > > On 31.07.2014, at 22:40, Frank Shearar <[hidden email]> wrote: > >> On 31 July 2014 21:37, Tobias Pape <[hidden email]> wrote: >>> Hi, >>> >>> On 31.07.2014, at 22:34, Yoshiki Ohshima <[hidden email]> wrote: >>> >>>> 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)? >>> >>> The diff is that big becaus OMeta is not in the trunk repository (and hench >>> not in the inbox). >>> Did you mean to commit it to http://www.squeaksource.com/OMeta ? >>> This is also where the config map is. >>> >>> Best >>> -Tobias >> >> Oh, I do like to see OMeta getting some love! >> >> That repo (http://www.squeaksource.com/OMeta) has _only "preload" and >> "postload" packages. Is that right? I'd sort've expected, from the >> names, that there would be a plain "ometa" package in the middle. > > It works like this: > > Load the config map, witch says: > Load the preload > Load the postload. > > The preload is: > “pre-compiled” Ometa in Squeak > The postload is: > ometa in ometa (compiled on load by the “pre-compiled” ometa version) > AND: mark both packages as non-dirty > > BTW: this is also one of the instances that use non-trivial PackageInfo trickey > > Best > -Tobias > > > > |
Free forum by Nabble | Edit this page |