analyzer/extensions.st
author Claus Gittinger <cg@exept.de>
Tue, 04 Mar 2014 21:27:43 +0100
changeset 284 c1b9188776ff
parent 276 61e163430728
child 376 a2656b27cace
permissions -rw-r--r--
moved
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
262
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     1
"{ Package: 'stx:goodies/petitparser/analyzer' }"!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     2
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     3
!PPActionParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     4
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     5
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     6
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self block = aParser block ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     7
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     8
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
     9
!PPDelegateParser methodsFor:'*petitanalyzer-transforming'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    10
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    11
replace: aParser with: anotherParser
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    12
	super replace: aParser with: anotherParser.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    13
	parser == aParser ifTrue: [ parser := anotherParser ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    14
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    15
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    16
!PPEpsilonParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    17
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    18
isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    19
	^ true
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    20
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    21
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    22
!PPFailingParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    23
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    24
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    25
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self message = aParser message ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    26
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    27
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    28
!PPLimitedRepeatingParser methodsFor:'*petitanalyzer-transforming'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    29
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    30
replace:aParser with:anotherParser
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    31
    super replace:aParser with:anotherParser.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    32
    limit == aParser ifTrue:[limit := anotherParser].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    33
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    34
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    35
!PPListParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    36
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    37
copyInContext: aDictionary seen: aSeenDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    38
	| copy copies |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    39
	aSeenDictionary at: self ifPresent: [ :value | ^ value ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    40
	copy := aSeenDictionary at: self put: self copy.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    41
	copies := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    42
	parsers do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    43
		| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    44
		result := each 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    45
			copyInContext: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    46
			seen: aSeenDictionary.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    47
		result isCollection
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    48
			ifTrue: [ copies addAll: result ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    49
			ifFalse: [ copies add: result ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    50
	^ copy
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    51
		setParsers: copies;
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    52
		yourself
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    53
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    54
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    55
!PPListParser methodsFor:'*petitanalyzer-transforming'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    56
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    57
replace: aParser with: anotherParser
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    58
	super replace: aParser with: anotherParser.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    59
	parsers keysAndValuesDo: [ :index :parser |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    60
		parser == aParser
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    61
			ifTrue: [ parsers at: index put: anotherParser ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    62
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    63
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    64
!PPLiteralParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    65
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    66
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    67
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self literal = aParser literal and: [ self message = aParser message ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    68
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    69
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    70
!PPOptionalParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    71
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    72
isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    73
	^ true
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    74
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    75
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    76
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    77
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    78
allNamedParsers
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    79
	"Answer all the named parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    80
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    81
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    82
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    83
	self allNamedParsersDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    84
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    85
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    86
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    87
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    88
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    89
allNamedParsersDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    90
	"Iterate over all the named parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    91
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    92
	self allParsersDo: [ :each | 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    93
		each name notNil
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    94
			ifTrue: [ aBlock value: each ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    95
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    96
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    97
!PPParser methodsFor:'*petitanalyzer-enumerating'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    98
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    99
allParsers
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   100
	"Answer all the parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   101
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   102
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   103
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   104
	self allParsersDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   105
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   106
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   107
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   108
!PPParser methodsFor:'*petitanalyzer-enumerating'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   109
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   110
allParsersDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   111
	"Iterate over all the parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   112
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   113
	self allParsersDo: aBlock seen: IdentitySet new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   114
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   115
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   116
!PPParser methodsFor:'*petitanalyzer-enumerating'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   117
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   118
allParsersDo: aBlock seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   119
	"Iterate over all the parse nodes of the receiver, do not visit and follow the ones contained in aSet."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   120
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   121
	(aSet includes: self)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   122
		ifTrue: [ ^ self ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   123
	aSet add: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   124
	aBlock value: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   125
	self children
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   126
		do: [ :each | each allParsersDo: aBlock seen: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   127
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   128
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   129
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   130
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   131
copyInContext: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   132
	^ self copyInContext: aDictionary seen: IdentityDictionary new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   133
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   134
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   135
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   136
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   137
copyInContext: aDictionary seen: aSeenDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   138
	| copy |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   139
	aSeenDictionary 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   140
		at: self 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   141
		ifPresent: [ :value | ^ value ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   142
	copy := aSeenDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   143
		at: self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   144
		put: self copy.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   145
	copy children do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   146
		copy
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   147
			replace: each
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   148
			with: (each copyInContext: aDictionary seen: aSeenDictionary) ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   149
	^ copy
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   150
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   151
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   152
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   153
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   154
cycleSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   155
	"Answer a set of all nodes that are within one or more cycles of left-recursion. This is generally not a problem if at least one of the nodes is memoized, but it might make the grammar very inefficient and should be avoided if possible."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   156
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   157
	| cycles |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   158
	cycles := IdentitySet new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   159
	self cycleSet: OrderedCollection new firstSets: self firstSets into: cycles.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   160
	^ cycles
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   161
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   162
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   163
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   164
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   165
cycleSet: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   166
	"PRIVATE: Answer the children that could be part of a cycle-set with the receiver, subclasses might restrict the number of children returned. aDictionary is pre-calcualted first-sets."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   167
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   168
	^ self children
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   169
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   170
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   171
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   172
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   173
cycleSet: aStack firstSets: aDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   174
	"PRIVATE: Try to find a cycle, where aStack contains the previously visited parsers. The method returns quickly when the receiver is a terminal, terminals cannot be part of a cycle. If aStack already contains the receiver, then we are in a cycle. In this case we don't process the children further and add the nodes to aSet."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   175
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   176
	| index |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   177
	self isTerminal
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   178
		ifTrue: [ ^ self ].	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   179
	(index := aStack indexOf: self) > 0
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   180
		ifTrue: [ ^ aSet addAll: (aStack copyFrom: index to: aStack size) ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   181
	aStack addLast: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   182
	(self cycleSet: aDictionary)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   183
		do: [ :each | each cycleSet: aStack firstSets: aDictionary into: aSet ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   184
	aStack removeLast
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   185
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   186
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   187
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   188
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   189
firstSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   190
	"Answer the first-set of the receiver. Note, this implementation is inefficient when called on different receivers of the same grammar, instead use #firstSets to calculate the first-sets at once."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   191
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   192
	^ self firstSets at: self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   193
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   194
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   195
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   196
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   197
firstSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   198
	"Answer a dictionary with all the parsers reachable from the receiver as key and their first-set as value. The first-set of a parser is the list of terminal parsers that begin the parser derivable from that parser."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   199
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   200
	| firstSets |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   201
	firstSets := IdentityDictionary new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   202
	self allParsersDo: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   203
		firstSets at: each put: (each isTerminal
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   204
			ifTrue: [ IdentitySet with: each ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   205
			ifFalse: [ IdentitySet new ]).
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   206
		each isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   207
			ifTrue: [ (firstSets at: each) add: PPSentinel instance ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   208
	[	| changed tally |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   209
		changed := false.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   210
		firstSets keysAndValuesDo: [ :parser :first |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   211
			tally := first size.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   212
			parser firstSets: firstSets into: first.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   213
			changed := changed or: [ tally ~= first size ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   214
		changed ] whileTrue.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   215
	^ firstSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   216
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   217
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   218
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   219
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   220
firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   221
	"PRIVATE: Try to add additional elements to the first-set aSet of the receiver, use the incomplete aFirstDictionary."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   222
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   223
	self children do: [ :parser | aSet addAll: (aFirstDictionary at: parser) ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   224
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   225
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   226
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   227
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   228
followSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   229
	"Answer the follow-set of the receiver starting at the receiver. Note, this implementation is inefficient when called on different receivers of the same grammar, instead use #followSets to calculate the follow-sets at once."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   230
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   231
	^ self followSets at: self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   232
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   233
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   234
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   235
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   236
followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   237
	"Answer a dictionary with all the parsers reachable from the receiver as key and their follow-set as value. The follow-set of a parser is the list of terminal parsers that can appear immediately to the right of that parser."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   238
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   239
	| current previous continue firstSets followSets |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   240
	current := previous := 0.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   241
	firstSets := self firstSets.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   242
	followSets := IdentityDictionary new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   243
	self allParsersDo: [ :each | followSets at: each put: IdentitySet new ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   244
	(followSets at: self) add: PPSentinel instance.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   245
	[	followSets keysAndValuesDo: [ :parser :follow |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   246
			parser 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   247
				followSets: followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   248
				firstSets: firstSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   249
				into: follow ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   250
		current := followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   251
			inject: 0
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   252
			into: [ :result :each | result + each size ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   253
		continue := previous < current.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   254
		previous := current.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   255
		continue ] whileTrue.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   256
	^ followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   257
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   258
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   259
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   260
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   261
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   262
	"PRIVATE: Try to add additional elements to the follow-set aSet of the receiver, use the incomplete aFollowDictionary and the complete aFirstDictionary."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   263
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   264
	self children do: [ :parser | (aFollowDictionary at: parser) addAll: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   265
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   266
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   267
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   268
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   269
innerChildren
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   270
	"Answer the inner children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   271
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   272
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   273
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   274
	self innerChildrenDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   275
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   276
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   277
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   278
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   279
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   280
innerChildrenDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   281
	"Iterate over the inner children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   282
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   283
	self innerChildrenDo: aBlock seen: IdentitySet new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   284
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   285
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   286
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   287
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   288
innerChildrenDo: aBlock seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   289
	"Iterate over the inner children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   290
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   291
	self children do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   292
		(aSet includes: each)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   293
			ifTrue: [ ^ self ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   294
		aSet add: each.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   295
		each name isNil ifTrue: [
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   296
			aBlock value: each.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   297
			each innerChildrenDo: aBlock seen: aSet ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   298
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   299
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   300
!PPParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   301
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   302
isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   303
	"Answer true if the receiver is a nullable parser, e.g. it can successfully parse nothing."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   304
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   305
	^ false
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   306
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   307
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   308
!PPParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   309
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   310
isTerminal
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   311
	"Answer true if the receiver is a terminal or leaf parser, that means it does not delegate to any other parser."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   312
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   313
	^ self children isEmpty
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   314
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   315
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   316
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   317
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   318
match: aParser inContext: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   319
	^ self match: aParser inContext: aDictionary seen: IdentitySet new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   320
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   321
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   322
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   323
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   324
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   325
	"This is the default implementation to match two parsers. This code can properly handle recursion. This is code is supposed to be overridden in subclasses that add new state."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   326
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   327
	(self == aParser or: [ anIdentitySet includes: self ])
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   328
		ifTrue: [ ^ true ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   329
	anIdentitySet add: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   330
	^ self class = aParser class and: [ self matchList: self children against: aParser children inContext: aDictionary seen: anIdentitySet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   331
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   332
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   333
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   334
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   335
matchList: matchList against: parserList inContext: aDictionary seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   336
	^ self matchList: matchList index: 1 against: parserList index: 1 inContext: aDictionary seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   337
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   338
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   339
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   340
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   341
matchList: matchList index: matchIndex against: parserList index: parserIndex inContext: aDictionary seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   342
	| parser currentIndex currentDictionary currentSeen parsers |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   343
	matchList size < matchIndex
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   344
		ifTrue: [ ^ parserList size < parserIndex ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   345
	parser := matchList at: matchIndex.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   346
	parser class = PPListPattern ifTrue: [
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   347
		currentIndex := parserIndex - 1.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   348
		[ currentDictionary := aDictionary copy.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   349
		currentSeen := aSet copy.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   350
		parserList size < currentIndex or: [ 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   351
			parsers := parserList copyFrom: parserIndex to: currentIndex.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   352
			(currentDictionary at: parser ifAbsentPut: [ parsers ]) = parsers and: [ 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   353
				(self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   354
					matchList: matchList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   355
					index: matchIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   356
					against: parserList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   357
					index: currentIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   358
					inContext: currentDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   359
					seen: currentSeen)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   360
					ifTrue: [ 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   361
						currentDictionary keysAndValuesDo: [ :key :value | aDictionary at: key put: value ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   362
						^ true ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   363
				false ] ] ] whileFalse: [ currentIndex := currentIndex + 1 ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   364
		^ false ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   365
	parserList size < parserIndex
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   366
		ifTrue: [ ^ false ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   367
	(parser match: (parserList at: parserIndex) inContext: aDictionary seen: aSet)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   368
		ifFalse: [ ^ false ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   369
	^ self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   370
		matchList: matchList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   371
		index: matchIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   372
		against: parserList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   373
		index: parserIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   374
		inContext: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   375
		seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   376
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   377
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   378
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   379
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   380
namedChildren
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   381
	"Answer the named children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   382
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   383
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   384
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   385
	self namedChildrenDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   386
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   387
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   388
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   389
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   390
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   391
namedChildrenDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   392
	"Iterate over the named children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   393
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   394
	self namedChildrenDo: aBlock seen: IdentitySet new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   395
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   396
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   397
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   398
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   399
namedChildrenDo: aBlock seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   400
	"Iterate over the named children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   401
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   402
	self children do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   403
		(aSet includes: each)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   404
			ifTrue: [ ^ self ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   405
		aSet add: each.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   406
		each name isNil
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   407
			ifTrue: [ each namedChildrenDo: aBlock seen: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   408
			ifFalse: [ aBlock value: each ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   409
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   410
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   411
!PPParser methodsFor:'*petitanalyzer-transforming'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   412
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   413
replace: aParser with: anotherParser
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   414
	"Replace the references of the receiver pointing to aParser with anotherParser."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   415
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   416
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   417
!PPParser methodsFor:'*petitanalyzer-transforming'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   418
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   419
transform: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   420
	"Answer a copy of all parsers reachable from the receiver transformed using aBlock."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   421
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   422
	| mapping root |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   423
	mapping := IdentityDictionary new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   424
	self allParsersDo: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   425
		mapping
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   426
			at: each
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   427
			put: (aBlock value: each copy) ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   428
	root := mapping at: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   429
	[	| changed |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   430
		changed := false.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   431
		root allParsersDo: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   432
			each children do: [ :old |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   433
				mapping at: old ifPresent: [ :new |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   434
					each replace: old with: new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   435
					changed := true ] ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   436
		changed ] whileTrue.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   437
	^ root
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   438
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   439
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   440
!PPPluggableParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   441
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   442
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   443
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self block = aParser block ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   444
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   445
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   446
!PPPredicateParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   447
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   448
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   449
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self block = aParser block and: [ self message = aParser message ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   450
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   451
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   452
!PPPredicateSequenceParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   453
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   454
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   455
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self size = aParser size ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   456
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   457
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   458
!PPRepeatingParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   459
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   460
isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   461
	^ min = 0
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   462
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   463
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   464
!PPRepeatingParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   465
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   466
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   467
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self min = aParser min and: [ self max = aParser max ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   468
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   469
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   470
!PPSequenceParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   471
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   472
cycleSet: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   473
	| firstSet |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   474
	1 to: parsers size do: [ :index |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   475
		firstSet := aDictionary at: (parsers at: index).
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   476
		(firstSet anySatisfy: [ :each | each isNullable ])
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   477
			ifFalse: [ ^ parsers copyFrom: 1 to: index ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   478
	^ parsers
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   479
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   480
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   481
!PPSequenceParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   482
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   483
firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   484
	| nullable |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   485
	parsers do: [ :parser |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   486
		nullable := false.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   487
		(aFirstDictionary at: parser) do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   488
			each isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   489
				ifTrue: [ nullable := true ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   490
				ifFalse: [ aSet add: each ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   491
		nullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   492
			ifFalse: [ ^ self ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   493
	aSet add: PPSentinel instance
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   494
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   495
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   496
!PPSequenceParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   497
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   498
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   499
	parsers keysAndValuesDo: [ :index :parser |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   500
		| followSet firstSet |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   501
		followSet := aFollowDictionary at: parser.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   502
		index = parsers size
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   503
			ifTrue: [ followSet addAll: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   504
			ifFalse: [
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   505
				(self class withAll: (parsers 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   506
					copyFrom: index + 1 to: parsers size))
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   507
						firstSets: aFirstDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   508
						into: (firstSet := IdentitySet new).
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   509
				(firstSet anySatisfy: [ :each | each isNullable ])
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   510
					ifTrue: [ followSet addAll: aSet ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   511
				followSet addAll: (firstSet 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   512
					reject: [ :each | each isNullable ]) ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   513
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   514
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   515
!PPTokenParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   516
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   517
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   518
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self tokenClass = aParser tokenClass ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   519
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   520
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   521
!stx_goodies_petitparser_analyzer class methodsFor:'documentation'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   522
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   523
extensionsVersion_CVS
284
Claus Gittinger <cg@exept.de>
parents: 276
diff changeset
   524
    ^ '$Header: /cvs/stx/stx/goodies/petitparser/analyzer/extensions.st,v 1.4 2014-03-04 20:27:43 cg Exp $'
262
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   525
! !