SmaCC__SmaCCRHS.st
author vranyj1
Thu, 10 Apr 2008 09:11:12 +0000
changeset 1 b8cca2663544
child 15 8b8cd1701c33
permissions -rw-r--r--
Initial import

"{ 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 $'
! !