SmaCC__SmaCCGrammar.st
author vranyj1
Wed, 17 Nov 2010 21:57:55 +0000
changeset 20 4ea23addc2c4
parent 15 8b8cd1701c33
child 25 5a6921729520
permissions -rw-r--r--
Makefile updated

"{ Package: 'stx:goodies/smaCC' }"

"{ NameSpace: SmaCC }"

Object subclass:#SmaCCGrammar
	instanceVariableNames:'type shiftReduceTable symbols tokens otherStartingSymbols'
	classVariableNames:'IgnoreCase MaximumCharacterValue'
	poolDictionaries:''
	category:'SmaCC-Parser Generator'
!

SmaCCGrammar comment:'SmaCCGrammar represents a LR(1) or a LALR(1) grammar.

Instance Variables:
	otherStartingSymbols	<Collection of: SmaCCSymbol>	other starting productions. The first production in the grammar is the defaulting starting position, but this can list other starting positions.
	shiftReduceTable	<Dictionary key: SmaCCSymbol value: SmaCCAction class>	when we have a shift/reduce conflict how should we handle it. This table contains the left/right associative rules. Left is a reduce action and right is a shift action.
	symbols	<OrderedCollection of: SmaCCSymbol>	all symbols in our grammar -- includes both terminal and non-terminal
	tokens	<Dictionary key: String value: SmaCCRegularExpressionNode>	the tokens for our scanner
	type	<Symbol>	the type of grammar (LALR1 or LR1)

'
!


!SmaCCGrammar class methodsFor:'instance creation'!

new
	^(super new)
		initialize;
		yourself
! !

!SmaCCGrammar class methodsFor:'accessing'!

ignoreCase
	^IgnoreCase
!

ignoreCase: aBoolean 
	IgnoreCase := aBoolean
!

maximumCharacterValue
	^MaximumCharacterValue
!

maximumCharacterValue: anInteger 
	MaximumCharacterValue := anInteger.
	SmaCCEdge initializeIsExpressions
! !

!SmaCCGrammar class methodsFor:'class initialization'!

initialize
        IgnoreCase := false.
        self maximumCharacterValue: 255

        "
         self initialize
        "
! !

!SmaCCGrammar methodsFor:'accessing'!

addEmptySymbol
	self addSymbol: SmaCCSymbol empty.
	self addSymbol: SmaCCSymbol error
!

addStartingSymbol: aSymbol 
	(otherStartingSymbols includes: aSymbol) 
		ifFalse: [otherStartingSymbols add: aSymbol]
!

allStartingSymbols
	"Return all starting symbols with the default starting symbol listed first."

	| startingSymbols default |
	default := self startSymbol.
	startingSymbols := otherStartingSymbols copy.
	startingSymbols remove: default ifAbsent: [].
	startingSymbols := startingSymbols collect: 
					[:each | 
					(SmaCCStartingSymbol name: 'B e g i n' , each name)
						addProduction: ((SmaCCRHS new)
									add: each;
									yourself);
						yourself].
	startingSymbols addFirst: default.
	^startingSymbols
!

emptySymbols
	^self symbols select: [:each | each isTerminal not and: [each isEmpty]]
!

initialItemSetFor: aSymbol 
	^(aSymbol asLRItemSet)
		type: type;
		yourself
!

makeGroupFor: aRHSCollection 
	| symbol name |
	name := aRHSCollection inject: ''
				into: [:sum :each | sum , ' | ' , each printString].
	symbol := self nonTerminalSymbolNamed: 'Group: ' , name.
	symbol isEmpty 
		ifTrue: 
			[(aRHSCollection allSatisfy: [:each | each size = 1]) 
				ifTrue: [aRHSCollection do: [:each | each reduceAction: '''1''']].
			aRHSCollection do: [:each | symbol addProduction: each]].
	^symbol
!

makeOptionalSymbolFor: aSymbol 
	| symbol |
	symbol := self nonTerminalSymbolNamed: 'Optional: ' , aSymbol printString.
	symbol isEmpty 
		ifTrue: 
			[symbol
				addProduction: ((SmaCCRHS new)
							reduceAction: 'nil';
							yourself);
				addProduction: ((SmaCCRHS new)
							add: aSymbol;
							reduceAction: '''1''';
							yourself)].
	^symbol
!

makeRepeatMultipleSymbolFor: aSymbol 
	| symbol |
	symbol := self 
				nonTerminalSymbolNamed: 'Repeat Multiple: ' , aSymbol printString.
	symbol isEmpty 
		ifTrue: 
			[symbol
				addProduction: ((SmaCCRHS new)
							add: aSymbol;
							reduceAction: 'OrderedCollection with: ''1''';
							yourself);
				addProduction: ((SmaCCRHS new)
							add: symbol;
							add: aSymbol;
							reduceAction: '''1'' add: ''2''; yourself';
							yourself)].
	^symbol
!

makeRepeatSymbolFor: aSymbol 
	| symbol |
	symbol := self nonTerminalSymbolNamed: 'Repeat: ' , aSymbol printString.
	symbol isEmpty 
		ifTrue: 
			[symbol
				addProduction: ((SmaCCRHS new)
							reduceAction: 'OrderedCollection new';
							yourself);
				addProduction: ((SmaCCRHS new)
							add: symbol;
							add: aSymbol;
							reduceAction: '''1'' add: ''2''; yourself';
							yourself)].
	^symbol
!

makeTokenIdMethodFor: aString 
	| token |
	token := (tokens includesKey: aString) 
				ifTrue: [self terminalSymbolNamed: aString]
				ifFalse: 
					[symbols detect: [:each | each name = aString]
						ifNone: [symbols add: (SmaCCTerminalSymbol name: aString)]].
	token createIdMethod: true
!

preferredActionFor: aGrammarSymbol 
	^shiftReduceTable at: aGrammarSymbol ifAbsent: [nil]
!

setStartSymbolIfNone: aGrammarSymbol 
	| startSymbol |
	self startSymbol notNil ifTrue: [^self].
	startSymbol := SmaCCStartingSymbol name: 'B e g i n'.
	self addSymbol: startSymbol.
	startSymbol addProduction: ((SmaCCRHS new)
				add: aGrammarSymbol;
				yourself)
!

startSymbol
	^symbols detect: [:each | each isStartingSymbol] ifNone: [nil]
!

tokens
	^tokens
!

unusedSymbols
	| nonTerminals problemSymbols todo symbol |
	nonTerminals := self symbols reject: [:each | each isTerminal].
	problemSymbols := nonTerminals asSet.
	problemSymbols remove: self startSymbol.
	todo := OrderedCollection with: self startSymbol.
	[todo isEmpty] whileFalse: 
			[symbol := todo removeFirst.
			symbol productionsDo: 
					[:rhs | 
					rhs do: 
							[:each | 
							each isTerminal 
								ifFalse: 
									[(problemSymbols includes: each) 
										ifTrue: 
											[todo add: each.
											problemSymbols remove: each]]]]].
	^problemSymbols
! !

!SmaCCGrammar methodsFor:'initialize-release'!

initialize
	type := #LALR1.
	symbols := OrderedCollection new.
	shiftReduceTable := Dictionary new.
	otherStartingSymbols := OrderedCollection new
!

tokens: aCollection
	tokens := aCollection
!

type: aSymbol
	type := aSymbol
! !

!SmaCCGrammar methodsFor:'precedence'!

leftPrecedenceFor: aGrammarSymbol 
	shiftReduceTable at: aGrammarSymbol put: SmaCCReduceAction
!

nonAssociativePrecedenceFor: aGrammarSymbol 
	shiftReduceTable at: aGrammarSymbol put: SmaCCRejectAction
!

rightPrecedenceFor: aGrammarSymbol 
	shiftReduceTable at: aGrammarSymbol put: SmaCCShiftAction
!

setOperatorPrecedenceFor: aGrammarSymbol to: anInteger
	aGrammarSymbol precedence: anInteger
! !

!SmaCCGrammar methodsFor:'private'!

addSymbol: aGrammarSymbol 
	^symbols add: aGrammarSymbol
!

calculateFirstSets
	| changed |
	changed := true.
	[changed] whileTrue: 
			[changed := false.
			self symbols 
				do: [:each | changed := changed | each calculateFirstTerminals]]
!

keywordTerminalNamed: aString 
	^symbols detect: [:each | each name = aString]
		ifNone: 
			[symbols addFirst: ((SmaCCTerminalSymbol name: aString)
						regularExpression: (((aString copyFrom: 2 to: aString size - 1) 
									copyReplaceAll: '""'
									with: '"') inject: nil
										into: 
											[:sum :each | 
											sum isNil 
												ifTrue: [SmaCCCharacterRENode characters: (String with: each)]
												ifFalse: [sum , (SmaCCCharacterRENode characters: (String with: each))]]);
						yourself)]
!

nonTerminalSymbolNamed: aString 
	^symbols detect: [:each | each name = aString]
		ifNone: [self addSymbol: (SmaCCNonTerminalSymbol name: aString)]
!

reduceTableIndexFor: aGrammarSymbol rhs: aRHS 
	| index |
	index := 0.
	self symbols do: 
			[:each | 
			each = aGrammarSymbol ifTrue: [^index + (each positionOf: aRHS)].
			index := index + each size].
	^0
!

symbols
	^symbols
!

symbols: aCollection
	symbols := aCollection
!

terminalSymbolNamed: aString 
	^symbols detect: [:each | each name = aString]
		ifNone: 
			[symbols add: ((SmaCCTerminalSymbol name: aString)
						regularExpression: (tokens at: aString);
						yourself)]
!

terminalSymbolNamed: aString ifAbsent: aBlock 
	^symbols detect: [:each | each name = aString]
		ifNone: 
			[symbols add: ((SmaCCTerminalSymbol name: aString)
						regularExpression: (tokens at: aString ifAbsent: [^aBlock value]);
						yourself)]
! !

!SmaCCGrammar class methodsFor:'documentation'!

version
    ^ '$Header: /opt/data/cvs/stx/goodies/smaCC/SmaCC__SmaCCGrammar.st,v 1.1 2006-02-09 21:17:17 vranyj1 Exp $'
!

version_SVN
    ^ '$Id$'
! !

SmaCCGrammar initialize!