'From Moshi of 3 March 2007 [latest update: #33] on 13 April 2007 at 10:51:13 am'!"Change Set:		PrecInTiles-yoDate:			13 April 2007Author:			Yoshiki OhshimaThis changes set changes the precedence rules in EToys tiles.  Instead of relying on the Morphic nested structure, this logic post-processes the generated parse tree by doing analysis based on operator procedence grammar way.  The assumption is that in the 'expression' part of tiles, a longer expression is always created by the extension arrow, therefore it is always totally right associative tree.  Based on this, walking throught the tree is almost the same as parsing flat structure, therefore a simple operator precedence grammar works."!Object subclass: #EToyExpressionTransformer	instanceVariableNames: 'method stack inputQueue encoder'	classVariableNames: ''	poolDictionaries: ''	category: 'System-Compiler'!!CompoundTileMorph methodsFor: 'code generation' stamp: 'yo 4/13/2007 10:07'!blockNodeElements: scriptPart with: encoder	| rows r |	rows _ scriptPart tileRows.	^ Array streamContents: [:strm |		1 to: rows size do: [:i |		r _ rows at: i.			r do: [:t | strm nextPut: (t parseNodeWith: encoder asStatement: true)].		].	].! !!CompoundTileMorph methodsFor: 'code generation' stamp: 'yo 4/13/2007 10:26'!parseNodeWith: encoder asStatement: aBoolean	^ self parseNodeWith: encoder.! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 21:36'!block: block	block statements do: [:stmt |		self stmt: stmt.	].! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 20:45'!inputQueueEmpty	^ inputQueue isEmpty! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 20:57'!inputQueueNext	| e f |	e _ inputQueue removeFirst.	inputQueue size > 0 ifTrue: [		f _ inputQueue removeFirst.		(f isMemberOf: MessageNode) ifTrue: [			self pushAMessageNode: f		] ifFalse: [			inputQueue addFirst: f		].	].	^ e.					! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 20:58'!inputQueuePeek	^ inputQueue size > 0 ifTrue: [inputQueue first] ifFalse: [nil]! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/13/2007 06:51'!message: msg	| node newNode |	self stmt: msg receiver.	1 to: msg arguments size do: [:ind |		node _ msg arguments at: ind.		(node isMemberOf: MessageNode) ifTrue: [			node isEToyBinaryExp ifTrue: [				newNode _ self newMessageFor: node.				msg arguments at: ind put: newNode.			] ifFalse: [				self message: node.			].		].		(node isMemberOf: BlockNode) ifTrue: [			self block: node		].	].! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 21:31'!newMessageFor: aMessageNode encoder: e	encoder _ e.	inputQueue _ OrderedCollection new: 3.	self pushAMessageNode: aMessageNode.	stack _ OrderedCollection new: 3.! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 21:15'!precl	stack size = 0 ifTrue: [^ 0].	stack size = 1 ifTrue: [^ self precl: stack last].	stack last isSymbol ifTrue: [^ 0].	^ self precl: (stack at: stack size - 1).! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 21:07'!precl: anObject	(#(#max: #min:) includes: anObject) ifTrue: [^ 1].	(#(#+ #-) includes: anObject) ifTrue: [^ 2].	(#(#* #/ #// #\\) includes: anObject) ifTrue: [^ 3].	^ 0.! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 20:58'!precr: anObject	anObject ifNil: [^ 0].	(#(#max: #min:) includes: anObject) ifTrue: [^ 1].	(#(#+ #-) includes: anObject) ifTrue: [^ 2].	(#(#* #/ #// #\\) includes: anObject) ifTrue: [^ 3].	^ 4.! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 20:35'!pushAMessageNode: node	| s |	node isEToyBinaryExp ifTrue: [		inputQueue addLast: node receiver.		inputQueue addLast: ((s _ node selector) isSymbol ifTrue: [s] ifFalse: [s key]).		inputQueue addLast: node arguments first.	] ifFalse: [		inputQueue addLast: node	].! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 21:22'!reduceOnStack	| list left sel right m |	list _ stack removeLast: 3.	left _ list at: 1.	sel _ list at: 2.	right _ list at: 3.	m _	 MessageNode new				receiver: left				selector: sel				arguments: (Array with: right)				precedence: (sel precedence)				from: encoder				sourceRange: nil.	stack addLast: m.! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 21:42'!stmt: stmt	| node newNode |	1 to: stmt arguments size do: [:ind |		node _ stmt arguments at: ind.		(node isMemberOf: MessageNode) ifTrue: [			node isEToyBinaryExp ifTrue: [				newNode _ self newMessageFor: node.				stmt arguments at: ind put: newNode.			] ifFalse: [				self message: node.			].		].		(node isMemberOf: BlockNode) ifTrue: [			self block: node		].	].! !!EToyExpressionTransformer methodsFor: 'accessing' stamp: 'yo 4/12/2007 21:16'!transform	| leftPrec rightPrec n |	[(self inputQueueEmpty and: [stack size = 1]) not] whileTrue: [		leftPrec _ self precl.		rightPrec _ self precr: (n _ self inputQueuePeek).		leftPrec >= rightPrec ifTrue: [			self reduceOnStack.		] ifFalse: [			self inputQueueNext.			stack addLast: n.		].	].	^ stack last.! !!ParseNode methodsFor: '*siss-interface' stamp: 'yo 4/13/2007 10:27'!isEToyBinaryExp	^ false.! !!MessageNode methodsFor: '*etoys-transform' stamp: 'yo 4/12/2007 20:44'!isEToyBinaryExp	| sel |	sel _ (sel _ self selector) isSymbol ifTrue: [sel] ifFalse: [sel key].	^ (#(#+ #- #* #/ #\\ #// #max: #min:) includes: sel).! !!PhraseTileMorph methodsFor: 'code generation' stamp: 'yo 4/13/2007 10:25'!assignmentNodeWith: encoder	| suffix rec sel args left op right m |	rec _ submorphs first parseNodeWith: encoder.		suffix _ submorphs second operatorForSexpAssignmentSuffix: submorphs second assignmentSuffix.	sel _ submorphs second assignmentRootForParseNode.	args _ WriteStream on: (Array new: 3).	(submorphs second isMemberOf: AssignmentTileMorph) ifFalse: [		args nextPut: (submorphs second parseNodeWith: encoder).		sel _ (sel, 'to:') asSymbol.	].	suffix isEmpty ifFalse: [		left _ self updatingOperatorNodeWith: encoder.		op _ (AssignmentTileMorph new operatorForAssignmentSuffix: suffix) asSymbol.		right _ self convertParseNode: (submorphs third parseNodeWith: encoder) with: encoder..		m _ MessageNode new				receiver: left				selector: op				arguments: (Array with: right)				precedence: (op precedence)				from: encoder				sourceRange: nil.		args nextPut: m.	] ifTrue: [		args nextPut: (self convertParseNode: (submorphs third parseNodeWith: encoder) with: encoder).	].	^ MessageNode new 				receiver: rec				selector: sel				arguments: args contents				precedence: (sel asSymbol precedence)				from: encoder				sourceRange: nil.! !!PhraseTileMorph methodsFor: 'code generation' stamp: 'yo 4/13/2007 10:32'!convertArgOfParseNode: message with: encoder	| e r |	e _ EToyExpressionTransformer new newMessageFor: message arguments first encoder: encoder.	r _ e transform.	message arguments at: 1 put: r.	^ message.! !!PhraseTileMorph methodsFor: 'code generation' stamp: 'yo 4/13/2007 10:33'!convertParseNode: message with: encoder	| e |	e _ EToyExpressionTransformer new newMessageFor: message encoder: encoder.	^  e transform.! !!PhraseTileMorph methodsFor: 'code generation' stamp: 'yo 4/13/2007 10:03'!parseNodeWith: encoder	^ self parseNodeWith: encoder asStatement: false.! !!PhraseTileMorph methodsFor: 'code generation' stamp: 'yo 4/13/2007 10:37'!parseNodeWith: encoder asStatement: aBoolean	| ret |	submorphs size >= 2 ifTrue: [		self isAssignment ifTrue: [			^ self assignmentNodeWith: encoder.		].		self isColorSeer ifTrue: [			ret _ self colorSeerNodeWith: encoder.		].		(true) ifTrue: [			ret _ self operatorNodeWith: encoder.			aBoolean ifTrue: [^ self convertArgOfParseNode: ret with: encoder].			^ ret.		].	].	ret _ submorphs first parseNodeWith: encoder.	aBoolean ifTrue: [^ self convertParseNode: ret with: encoder].	^ ret.! !!ScriptEditorMorph methodsFor: 'other' stamp: 'yo 4/13/2007 10:06'!parseNodeWith: encoder	| statements ret |	statements _ WriteStream on: (Array new: self tileRows size).	self tileRows do: [:r | 		r do: [:m | 			((m isKindOf: TileMorph) 				or: [(m isKindOf: CompoundTileMorph)					or: [m isKindOf: PhraseTileMorph]]) ifTrue: [						statements nextPut: (m parseNodeWith: encoder asStatement: true)]]].	statements _ statements contents.	ret _ ReturnNode new expr: (encoder encodeVariable: 'self').	^ BlockNode new arguments: #() statements: (statements copyWith: ret) returns: true from: encoder.! !EToyExpressionTransformer removeSelector: #initialize!EToyExpressionTransformer removeSelector: #inpQueueNext!EToyExpressionTransformer removeSelector: #left!EToyExpressionTransformer removeSelector: #leftOp!EToyExpressionTransformer removeSelector: #leftOp:!EToyExpressionTransformer removeSelector: #left:!EToyExpressionTransformer removeSelector: #middle!EToyExpressionTransformer removeSelector: #middle:!EToyExpressionTransformer removeSelector: #newFor:!EToyExpressionTransformer removeSelector: #newFor:encoder:!EToyExpressionTransformer removeSelector: #newMessageFor:!EToyExpressionTransformer removeSelector: #prec:!EToyExpressionTransformer removeSelector: #right!EToyExpressionTransformer removeSelector: #rightOp!EToyExpressionTransformer removeSelector: #rightOp:!EToyExpressionTransformer removeSelector: #right:!EToyExpressionTransformer removeSelector: #transformStatement:!