Class { #name : 'PPCContext', #superclass : 'PPStream', #instVars : [ 'root', 'properties', 'globals', 'furthestFailure', 'compiledParser', 'ws', 'waterPosition', 'columns' ], #category : 'PetitCompiler-Context' } { #category : 'as yet unclassified' } PPCContext class >> new [ ^ self basicNew initialize ] { #category : 'as yet unclassified' } PPCContext class >> on: aPPParser stream: aStream [ ^ self basicNew initialize; root: aPPParser; stream: aStream asPetitStream; yourself ] { #category : 'converting' } PPCContext >> asCompiledParserContext [ ^ self ] { #category : 'whitespace' } PPCContext >> atWs [ ^ position == ws ] { #category : 'indentation' } PPCContext >> column [ ^ self columns at: (position + 1) ] { #category : 'indentation' } PPCContext >> columns [ | column tmpPosition | columns isNil ifTrue: [ tmpPosition := position. columns := Array new: readLimit + 1. column := 1. 0 to: readLimit do: [ :index | position := index. self isStartOfLine ifTrue: [ column := 1 ]. columns at: (index + 1) put: column. column := column + 1. ]. position := tmpPosition. ]. ^ columns ] { #category : 'initialization' } PPCContext >> compiledParser [ ^ compiledParser ] { #category : 'initialization' } PPCContext >> compiledParser: anObject [ compiledParser := anObject ] { #category : 'failures' } PPCContext >> furthestFailure [ ^ furthestFailure ] { #category : 'accessing-globals' } PPCContext >> globalAt: aKey [ "Answer the global property value associated with aKey." ^ self globalAt: aKey ifAbsent: [ self error: 'Property not found' ] ] { #category : 'accessing-globals' } PPCContext >> globalAt: aKey ifAbsent: aBlock [ "Answer the global property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock." ^ globals isNil ifTrue: [ aBlock value ] ifFalse: [ globals at: aKey ifAbsent: aBlock ] ] { #category : 'accessing-globals' } PPCContext >> globalAt: aKey ifAbsentPut: aBlock [ "Answer the global property associated with aKey or, if aKey isn't found store the result of evaluating aBlock as new value." ^ self globalAt: aKey ifAbsent: [ self globalAt: aKey put: aBlock value ] ] { #category : 'accessing-globals' } PPCContext >> globalAt: aKey put: anObject [ "Set the global property at aKey to be anObject. If aKey is not found, create a new entry for aKey and set is value to anObject. Answer anObject." ^ (globals ifNil: [ globals := Dictionary new: 1 ]) at: aKey put: anObject ] { #category : 'whitespace' } PPCContext >> goUpTo: char [ [ position < readLimit ] whileTrue: [ (collection at: position + 1) == char ifTrue: [ position := position + 1. ^ char ] . position := position + 1. ] ] { #category : 'gt' } PPCContext >> gtIndentStack: composite [ composite list title: 'Indent Stack'; display: [ :context | context indentStack contents ] ] { #category : 'gt' } PPCContext >> gtProperties: composite [ composite table title: 'Properties'; column: 'Key' evaluated: [ :each | each key printString ]; column: 'Value' evaluated: [ :each | each value printString ]; display: [ :node | (node properties ifNil: [ Dictionary new ]) associations ] ] { #category : 'accessing-globals' } PPCContext >> hasGlobal: aKey [ "Test if the global property aKey is present." ^ globals notNil and: [ globals includesKey: aKey ] ] { #category : 'accessing-properties' } PPCContext >> hasProperties [ ^ properties isNil not and: [ properties isEmpty not ] ] { #category : 'accessing-properties' } PPCContext >> hasProperty: aKey [ "Test if the property aKey is present." ^ properties notNil and: [ properties includesKey: aKey ] ] { #category : 'ruby' } PPCContext >> heredocId [ ^ self globalAt: #heredocId ifAbsent: nil ] { #category : 'ruby' } PPCContext >> heredocId: value [ self globalAt: #heredocId put: value ] { #category : 'memoization' } PPCContext >> identifier [ ^ collection ] { #category : 'indentation' } PPCContext >> indentStack [ ^ self propertyAt: #indentStack ifAbsentPut: [ IndentStack new ] ] { #category : 'initialization' } PPCContext >> initialize [ super initialize. rc := 0. "Note a failure at -1" furthestFailure := PPFailure new position: -1; yourself. ] { #category : 'initialization' } PPCContext >> initializeFor: parser [ rc := 0. root := parser. ] { #category : 'accessing-globals' } PPCContext >> invoke: parser [ ^ parser parseOn: self ] { #category : 'profiling' } PPCContext >> islandInvoke [ ] { #category : 'profiling' } PPCContext >> islandMemoHit [ ] { #category : 'profiling' } PPCContext >> islandMemoized [ ] { #category : 'memoization' } PPCContext >> lwRemember [ ^ position ] { #category : 'memoization' } PPCContext >> lwRestore: aPPContextMemento [ position := aPPContextMemento. ] { #category : 'failures' } PPCContext >> noteFailure: aPPFailure [ (aPPFailure position > furthestFailure position) ifTrue: [ furthestFailure := aPPFailure ]. ] { #category : 'accessing-globals' } PPCContext >> peek2 [ position = readLimit ifTrue: [ ^ nil ]. ^ collection at: (position + 1) ] { #category : 'ruby' } PPCContext >> percentStringEnd [ ^ self globalAt: #percentStringEnd ifAbsent: nil ] { #category : 'ruby' } PPCContext >> percentStringStart: value [ | endValue | endValue := value. (value == $[) ifTrue: [ endValue := $] ]. (value == $() ifTrue: [ endValue := $) ]. (value == ${) ifTrue: [ endValue := $} ]. self globalAt: #percentStringStart put: value. self globalAt: #percentStringEnd put: endValue ] { #category : 'accessing-properties' } PPCContext >> properties [ ^ properties ifNil: [ properties := Dictionary new ] ] { #category : 'accessing-properties' } PPCContext >> propertyAt: aKey [ "Answer the property value associated with aKey." ^ self propertyAt: aKey ifAbsent: [ self error: 'Property not found' ] ] { #category : 'accessing-properties' } PPCContext >> propertyAt: aKey ifAbsent: aBlock [ "Answer the property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock." ^ properties isNil ifTrue: [ aBlock value ] ifFalse: [ properties at: aKey ifAbsent: aBlock ] ] { #category : 'accessing-properties' } PPCContext >> propertyAt: aKey ifAbsentPut: aBlock [ "Answer the property associated with aKey or, if aKey isn't found store the result of evaluating aBlock as new value." ^ self propertyAt: aKey ifAbsent: [ self propertyAt: aKey put: aBlock value ] ] { #category : 'accessing-properties' } PPCContext >> propertyAt: aKey put: anObject [ "Set the property at aKey to be anObject. If aKey is not found, create a new entry for aKey and set is value to anObject. Answer anObject." ^ (properties ifNil: [ properties := Dictionary new: 1 ]) at: aKey put: anObject ] { #category : 'memoization' } PPCContext >> remember [ | memento | memento := PPCContextMemento new position: position; yourself. self rememberProperties: memento. ^ memento ] { #category : 'memoization' } PPCContext >> rememberProperties: aPPContextMemento [ properties ifNil: [ ^ self ]. properties keysAndValuesDo: [ :key :value | aPPContextMemento propertyAt: key put: value ]. ] { #category : 'accessing-globals' } PPCContext >> removeGlobal: aKey [ "Remove the property with aKey. Answer the property or raise an error if aKey isn't found." ^ self removeGlobal: aKey ifAbsent: [ self error: 'Property not found' ] ] { #category : 'accessing-globals' } PPCContext >> removeGlobal: aKey ifAbsent: aBlock [ "Remove the global property with aKey. Answer the value or, if aKey isn't found, answer the result of evaluating aBlock." | answer | globals isNil ifTrue: [ ^ aBlock value ]. answer := globals removeKey: aKey ifAbsent: aBlock. globals isEmpty ifTrue: [ globals := nil ]. ^ answer ] { #category : 'accessing-properties' } PPCContext >> removeProperty: aKey [ "Remove the property with aKey. Answer the property or raise an error if aKey isn't found." ^ self removeProperty: aKey ifAbsent: [ self error: 'Property not found' ] ] { #category : 'accessing-properties' } PPCContext >> removeProperty: aKey ifAbsent: aBlock [ "Remove the property with aKey. Answer the value or, if aKey isn't found, answer the result of evaluating aBlock." | answer | properties isNil ifTrue: [ ^ aBlock value ]. answer := properties removeKey: aKey ifAbsent: aBlock. properties isEmpty ifTrue: [ properties := nil ]. ^ answer ] { #category : 'initialization' } PPCContext >> reset [ properties := nil. globals := nil. waterPosition := nil. ws := nil ] { #category : 'memoization' } PPCContext >> restore: aPPContextMemento [ " position := aPPContextMemento. " position := aPPContextMemento position. self restoreProperties: aPPContextMemento. ] { #category : 'memoization' } PPCContext >> restoreProperties: aPPContextMemento [ properties ifNil: [ ^ self ]. properties keysDo: [ :key | (aPPContextMemento hasProperty: key) ifTrue: [ properties at: key put: (aPPContextMemento propertyAt: key) ] ifFalse: [ properties removeKey: key ]. ]. aPPContextMemento keysAndValuesDo: [ :key :value | properties at: key put: value ] ] { #category : 'acessing' } PPCContext >> root [ ^ root ] { #category : 'whitespace' } PPCContext >> setWs [ ^ ws := position ] { #category : 'acessing' } PPCContext >> stream [ ^ self ] { #category : 'acessing' } PPCContext >> stream: aStream [ collection := aStream collection. position := aStream position. readLimit := collection size. newlines := nil. columns := nil. ws := nil. ] { #category : 'islands' } PPCContext >> waterPosition [ "^ self globalAt: #waterPosition ifAbsentPut: [ nil ]" ^ waterPosition ] { #category : 'islands' } PPCContext >> waterPosition: value [ " ^ self globalAt: #waterPosition put: value" waterPosition := value ] { #category : 'profiling' } PPCContext >> waterToken [ ] { #category : 'whitespace' } PPCContext >> ws [ ^ ws ] { #category : 'whitespace' } PPCContext >> ws: anInteger [ ws := anInteger ]