[squeak-dev] The Inbox: OMeta2-Preload-yo.15.mcz
commits at source.squeak.org
commits at source.squeak.org
Thu Jul 31 20:31:22 UTC 2014
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!
More information about the Squeak-dev
mailing list
|