SmaCC__SmaCCRHS.st
changeset 1 b8cca2663544
child 15 8b8cd1701c33
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SmaCC__SmaCCRHS.st	Thu Apr 10 09:11:12 2008 +0000
@@ -0,0 +1,169 @@
+"{ Package: 'stx:goodies/smaCC' }"
+
+"{ NameSpace: SmaCC }"
+
+Object subclass:#SmaCCRHS
+	instanceVariableNames:'collection reduceAction variableNames'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'SmaCC-Parser Generator'
+!
+
+SmaCCRHS comment:'SmaCCRHS represents the right hand side of the production.
+
+Instance variables:
+	collection	<OrderedCollection of: SmaCCSymbol> the collection of symbols that represent the rhs
+	grammar <SmaCCGrammar> the grammar that the production is in
+	variableNames	<Dictionary key: String value: Integer>	the name of each symbol in the rhs. These names can be used in the {} code blocks.'
+!
+
+
+!SmaCCRHS class methodsFor:'instance creation'!
+
+new
+	^(super new)
+		initialize;
+		yourself
+! !
+
+!SmaCCRHS methodsFor:'accessing'!
+
+add: aGrammarSymbol 
+	collection add: aGrammarSymbol
+!
+
+at: anInteger 
+	^collection at: anInteger
+!
+
+do: aBlock
+	collection do: aBlock
+!
+
+firstTerminals
+	| items |
+	collection isEmpty ifTrue: [^Set with: SmaCCSymbol empty].
+	items := Set new.
+	1 to: collection size
+		do: 
+			[:index | 
+			items addAll: (collection at: index) firstTerminals.
+			(items includes: SmaCCSymbol empty) 
+				ifTrue: [index < collection size ifTrue: [items remove: SmaCCSymbol empty]]
+				ifFalse: [^items]].
+	^items
+!
+
+nameLastItem: aString 
+	variableNames at: aString put: collection size
+!
+
+reduceAction
+	^reduceAction
+!
+
+reduceAction: anObject
+	reduceAction := anObject
+!
+
+size
+	^collection size
+! !
+
+!SmaCCRHS methodsFor:'comparing'!
+
+= aRHS 
+	^self class = aRHS class and: [collection = aRHS collection]
+!
+
+hash
+	^self class hash bitXor: (collection hash bitShift: 14)
+! !
+
+!SmaCCRHS methodsFor:'initialize-release'!
+
+initialize
+	collection := OrderedCollection new.
+	reduceAction := nil.
+	variableNames := Dictionary new
+! !
+
+!SmaCCRHS methodsFor:'printing'!
+
+printOn: aStream 
+	^collection do: [:each | each printOn: aStream]
+		separatedBy: [aStream space]
+! !
+
+!SmaCCRHS methodsFor:'private'!
+
+collection
+	^collection
+!
+
+defaultReduceAction
+	^#reduceFor:
+! !
+
+!SmaCCRHS methodsFor:'public'!
+
+compileSourceFor: aGrammarSymbol in: aClass
+        | action rewriter parseTree methodName |
+        action := self reduceAction.
+        action isNil ifTrue: [^self defaultReduceAction].
+        parseTree := RBParser parseExpression: action
+                                onError: 
+                                        [:s :p | 
+                                        Smalltalk isSmalltalkX ifTrue:[
+                                            SmaCCCompilationNotification raiseSignal: 'Invalid Smalltalk code in reduction rule'
+                                                    with: aGrammarSymbol name , ' : ' , self printString , '\\' withCRs , action.
+                                        ] ifFalse:[
+                                            SmaCCCompilationNotification signal: 'Invalid Smalltalk code in reduction rule'
+                                                    with: aGrammarSymbol name , ' : ' , self printString , '\\' withCRs , action.
+                                        ].
+                                        ^self defaultReduceAction].
+        (parseTree isLiteral and: 
+                        [parseTree value isSymbol 
+                                and: [parseTree value argumentCount <= 1 and: [aClass definesMethod: parseTree value]]]) 
+                ifTrue: [^parseTree value].
+        rewriter := self parseTreeRewriter.
+        rewriter executeTree: parseTree.
+        parseTree := rewriter tree.
+        methodName := ('reduceActionFor' , (self safeMethodNameFor: aGrammarSymbol) 
+                                , (aGrammarSymbol positionOf: self) printString , ':') 
+                                asSymbol.
+        parseTree isSequence 
+                ifFalse: [parseTree := RBSequenceNode statements: (Array with: parseTree)].
+        parseTree := RBMethodNode 
+                                selector: methodName
+                                arguments: (Array with: (RBVariableNode named: 'nodes'))
+                                body: parseTree.
+        parseTree addReturn.
+        aClass compile: parseTree formattedCode classified: 'generated-reduction actions'.
+        ^methodName
+!
+
+parseTreeRewriter
+	| rewriter |
+	rewriter := ParseTreeRewriter new.
+	1 to: self size
+		do: 
+			[:i | 
+			rewriter replace: i printString storeString
+				with: '(nodes at: ' , i printString , ')'].
+	variableNames keysAndValuesDo: 
+			[:key :value | 
+			rewriter replace: key with: '(nodes at: ' , value printString , ')'].
+	^rewriter
+!
+
+safeMethodNameFor: aGrammarSymbol 
+	^aGrammarSymbol printString 
+		collect: [:each | each isAlphaNumeric ifTrue: [each] ifFalse: [$_]]
+! !
+
+!SmaCCRHS class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /opt/data/cvs/stx/goodies/smaCC/SmaCC__SmaCCRHS.st,v 1.1 2006-02-09 21:14:42 vranyj1 Exp $'
+! !