[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