analyzer/extensions.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 03 Oct 2014 02:45:16 +0100
changeset 378 53d66ecfeb1b
parent 376 a2656b27cace
child 381 0bbbcf5da2d4
permissions -rw-r--r--
Merged in latest version from Moose repository Name: PetitAnalyzer-DiegoLont.46 Author: DiegoLont Time: 02-09-2013, 12:37:58 PM UUID: 89f155fa-89b4-4bb7-b76e-0f8485be4a56 Repository: http://smalltalkhub.com/mc/Moose/PetitParser/main
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
378
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    30
replace: aParser with: anotherParser
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    31
	super replace: aParser with: anotherParser.
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    32
	limit == aParser ifTrue: [ limit := anotherParser ]
262
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
378
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    70
!PPNotParser methodsFor:'*petitanalyzer-private'!
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    71
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    72
firstSets: aFirstDictionary into: aSet
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    73
	
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    74
! !
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    75
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    76
!PPNotParser methodsFor:'*petitanalyzer-testing'!
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    77
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    78
isFirstSetTerminal
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    79
	^ true
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    80
! !
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
    81
262
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    82
!PPOptionalParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    83
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    84
isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    85
	^ true
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    86
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    87
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    88
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    89
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    90
allNamedParsers
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    91
	"Answer all the named parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    92
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    93
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    94
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    95
	self allNamedParsersDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    96
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    97
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    98
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
    99
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   100
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   101
allNamedParsersDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   102
	"Iterate over all the named parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   103
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   104
	self allParsersDo: [ :each | 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   105
		each name notNil
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   106
			ifTrue: [ aBlock value: each ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   107
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   108
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   109
!PPParser methodsFor:'*petitanalyzer-enumerating'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   110
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   111
allParsers
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   112
	"Answer all the parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   113
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   114
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   115
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   116
	self allParsersDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   117
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   118
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   119
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   120
!PPParser methodsFor:'*petitanalyzer-enumerating'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   121
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   122
allParsersDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   123
	"Iterate over all the parse nodes of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   124
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   125
	self allParsersDo: aBlock seen: IdentitySet new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   126
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   127
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   128
!PPParser methodsFor:'*petitanalyzer-enumerating'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   129
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   130
allParsersDo: aBlock seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   131
	"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
   132
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   133
	(aSet includes: self)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   134
		ifTrue: [ ^ self ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   135
	aSet add: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   136
	aBlock value: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   137
	self children
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   138
		do: [ :each | each allParsersDo: aBlock seen: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   139
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   140
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   141
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   142
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   143
copyInContext: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   144
	^ self copyInContext: aDictionary seen: IdentityDictionary new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   145
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   146
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   147
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   148
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   149
copyInContext: aDictionary seen: aSeenDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   150
	| copy |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   151
	aSeenDictionary 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   152
		at: self 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   153
		ifPresent: [ :value | ^ value ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   154
	copy := aSeenDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   155
		at: self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   156
		put: self copy.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   157
	copy children do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   158
		copy
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   159
			replace: each
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   160
			with: (each copyInContext: aDictionary seen: aSeenDictionary) ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   161
	^ copy
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   162
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   163
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   164
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   165
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   166
cycleSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   167
	"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
   168
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   169
	| cycles |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   170
	cycles := IdentitySet new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   171
	self cycleSet: OrderedCollection new firstSets: self firstSets into: cycles.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   172
	^ cycles
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   173
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   174
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   175
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   176
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   177
cycleSet: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   178
	"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
   179
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   180
	^ self children
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   181
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   182
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   183
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   184
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   185
cycleSet: aStack firstSets: aDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   186
	"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
   187
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   188
	| index |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   189
	self isTerminal
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   190
		ifTrue: [ ^ self ].	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   191
	(index := aStack indexOf: self) > 0
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   192
		ifTrue: [ ^ aSet addAll: (aStack copyFrom: index to: aStack size) ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   193
	aStack addLast: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   194
	(self cycleSet: aDictionary)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   195
		do: [ :each | each cycleSet: aStack firstSets: aDictionary into: aSet ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   196
	aStack removeLast
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   197
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   198
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   199
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   200
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   201
firstSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   202
	"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
   203
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   204
	^ self firstSets at: self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   205
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   206
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   207
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   208
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   209
firstSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   210
	"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
   211
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   212
	| firstSets |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   213
	firstSets := IdentityDictionary new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   214
	self allParsersDo: [ :each |
378
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   215
		firstSets at: each put: (each isFirstSetTerminal
262
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   216
			ifTrue: [ IdentitySet with: each ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   217
			ifFalse: [ IdentitySet new ]).
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   218
		each isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   219
			ifTrue: [ (firstSets at: each) add: PPSentinel instance ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   220
	[	| changed tally |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   221
		changed := false.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   222
		firstSets keysAndValuesDo: [ :parser :first |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   223
			tally := first size.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   224
			parser firstSets: firstSets into: first.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   225
			changed := changed or: [ tally ~= first size ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   226
		changed ] whileTrue.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   227
	^ firstSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   228
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   229
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   230
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   231
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   232
firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   233
	"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
   234
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   235
	self children do: [ :parser | aSet addAll: (aFirstDictionary at: parser) ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   236
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   237
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   238
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   239
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   240
followSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   241
	"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
   242
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   243
	^ self followSets at: self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   244
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   245
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   246
!PPParser methodsFor:'*petitanalyzer-querying'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   247
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   248
followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   249
	"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
   250
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   251
	| current previous continue firstSets followSets |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   252
	current := previous := 0.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   253
	firstSets := self firstSets.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   254
	followSets := IdentityDictionary new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   255
	self allParsersDo: [ :each | followSets at: each put: IdentitySet new ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   256
	(followSets at: self) add: PPSentinel instance.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   257
	[	followSets keysAndValuesDo: [ :parser :follow |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   258
			parser 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   259
				followSets: followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   260
				firstSets: firstSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   261
				into: follow ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   262
		current := followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   263
			inject: 0
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   264
			into: [ :result :each | result + each size ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   265
		continue := previous < current.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   266
		previous := current.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   267
		continue ] whileTrue.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   268
	^ followSets
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   269
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   270
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   271
!PPParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   272
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   273
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   274
	"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
   275
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   276
	self children do: [ :parser | (aFollowDictionary at: parser) addAll: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   277
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   278
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   279
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   280
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   281
innerChildren
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   282
	"Answer the inner children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   283
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   284
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   285
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   286
	self innerChildrenDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   287
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   288
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   289
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   290
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   291
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   292
innerChildrenDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   293
	"Iterate over the inner children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   294
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   295
	self innerChildrenDo: aBlock seen: IdentitySet new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   296
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   297
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   298
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   299
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   300
innerChildrenDo: aBlock seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   301
	"Iterate over the inner children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   302
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   303
	self children do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   304
		(aSet includes: each)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   305
			ifTrue: [ ^ self ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   306
		aSet add: each.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   307
		each name isNil ifTrue: [
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   308
			aBlock value: each.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   309
			each innerChildrenDo: aBlock seen: aSet ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   310
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   311
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   312
!PPParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   313
378
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   314
isFirstSetTerminal
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   315
	"Answer true if the receiver is a terminal or leaf parser, that means it does not delegate to any other parser."
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   316
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   317
	^ self children isEmpty
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   318
! !
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   319
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   320
!PPParser methodsFor:'*petitanalyzer-testing'!
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   321
262
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   322
isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   323
	"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
   324
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   325
	^ false
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   326
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   327
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   328
!PPParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   329
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   330
isTerminal
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   331
	"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
   332
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   333
	^ self children isEmpty
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   334
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   335
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   336
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   337
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   338
match: aParser inContext: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   339
	^ self match: aParser inContext: aDictionary seen: IdentitySet new
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   340
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   341
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   342
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   343
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   344
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   345
	"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
   346
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   347
	(self == aParser or: [ anIdentitySet includes: self ])
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   348
		ifTrue: [ ^ true ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   349
	anIdentitySet add: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   350
	^ 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
   351
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   352
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   353
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   354
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   355
matchList: matchList against: parserList inContext: aDictionary seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   356
	^ self matchList: matchList index: 1 against: parserList index: 1 inContext: aDictionary seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   357
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   358
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   359
!PPParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   360
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   361
matchList: matchList index: matchIndex against: parserList index: parserIndex inContext: aDictionary seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   362
	| parser currentIndex currentDictionary currentSeen parsers |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   363
	matchList size < matchIndex
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   364
		ifTrue: [ ^ parserList size < parserIndex ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   365
	parser := matchList at: matchIndex.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   366
	parser class = PPListPattern ifTrue: [
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   367
		currentIndex := parserIndex - 1.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   368
		[ currentDictionary := aDictionary copy.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   369
		currentSeen := aSet copy.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   370
		parserList size < currentIndex or: [ 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   371
			parsers := parserList copyFrom: parserIndex to: currentIndex.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   372
			(currentDictionary at: parser ifAbsentPut: [ parsers ]) = parsers and: [ 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   373
				(self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   374
					matchList: matchList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   375
					index: matchIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   376
					against: parserList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   377
					index: currentIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   378
					inContext: currentDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   379
					seen: currentSeen)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   380
					ifTrue: [ 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   381
						currentDictionary keysAndValuesDo: [ :key :value | aDictionary at: key put: value ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   382
						^ true ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   383
				false ] ] ] whileFalse: [ currentIndex := currentIndex + 1 ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   384
		^ false ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   385
	parserList size < parserIndex
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   386
		ifTrue: [ ^ false ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   387
	(parser match: (parserList at: parserIndex) inContext: aDictionary seen: aSet)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   388
		ifFalse: [ ^ false ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   389
	^ self
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   390
		matchList: matchList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   391
		index: matchIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   392
		against: parserList
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   393
		index: parserIndex + 1
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   394
		inContext: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   395
		seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   396
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   397
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   398
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   399
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   400
namedChildren
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   401
	"Answer the named children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   402
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   403
	| result |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   404
	result := OrderedCollection new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   405
	self namedChildrenDo: [ :parser | result addLast: parser ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   406
	^ result
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   407
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   408
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   409
!PPParser methodsFor:'*petitanalyzer-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   410
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   411
namedChildrenDo: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   412
	"Iterate over the named children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   413
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   414
	self namedChildrenDo: aBlock seen: IdentitySet new
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-named'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   418
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   419
namedChildrenDo: aBlock seen: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   420
	"Iterate over the named children of the receiver."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   421
	
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   422
	self children do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   423
		(aSet includes: each)
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   424
			ifTrue: [ ^ self ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   425
		aSet add: each.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   426
		each name isNil
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   427
			ifTrue: [ each namedChildrenDo: aBlock seen: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   428
			ifFalse: [ aBlock value: each ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   429
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   430
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   431
!PPParser methodsFor:'*petitanalyzer-transforming'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   432
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   433
replace: aParser with: anotherParser
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   434
	"Replace the references of the receiver pointing to aParser with anotherParser."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   435
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   436
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   437
!PPParser methodsFor:'*petitanalyzer-transforming'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   438
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   439
transform: aBlock
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   440
	"Answer a copy of all parsers reachable from the receiver transformed using aBlock."
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   441
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   442
	| mapping root |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   443
	mapping := IdentityDictionary new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   444
	self allParsersDo: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   445
		mapping
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   446
			at: each
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   447
			put: (aBlock value: each copy) ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   448
	root := mapping at: self.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   449
	[	| changed |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   450
		changed := false.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   451
		root allParsersDo: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   452
			each children do: [ :old |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   453
				mapping at: old ifPresent: [ :new |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   454
					each replace: old with: new.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   455
					changed := true ] ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   456
		changed ] whileTrue.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   457
	^ root
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   458
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   459
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   460
!PPPluggableParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   461
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   462
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   463
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self block = aParser block ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   464
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   465
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   466
!PPPredicateParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   467
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   468
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   469
	^ (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
   470
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   471
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   472
!PPPredicateSequenceParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   473
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   474
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   475
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self size = aParser size ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   476
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   477
378
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   478
!PPRepeatingParser methodsFor:'*petitanalyzer-private'!
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   479
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   480
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   481
	| firstSet |
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   482
	super followSets: aFollowDictionary firstSets:  aFirstDictionary into: aSet.
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   483
	
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   484
	firstSet := aFirstDictionary at: self.
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   485
	self children do: [:p | (aFollowDictionary at: p) addAll: (firstSet reject: [:each | each isNullable]) ]
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   486
! !
53d66ecfeb1b Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 376
diff changeset
   487
262
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   488
!PPRepeatingParser methodsFor:'*petitanalyzer-testing'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   489
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   490
isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   491
	^ min = 0
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   492
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   493
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   494
!PPRepeatingParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   495
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   496
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   497
	^ (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
   498
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   499
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   500
!PPSequenceParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   501
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   502
cycleSet: aDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   503
	| firstSet |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   504
	1 to: parsers size do: [ :index |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   505
		firstSet := aDictionary at: (parsers at: index).
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   506
		(firstSet anySatisfy: [ :each | each isNullable ])
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   507
			ifFalse: [ ^ parsers copyFrom: 1 to: index ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   508
	^ parsers
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   509
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   510
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   511
!PPSequenceParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   512
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   513
firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   514
	| nullable |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   515
	parsers do: [ :parser |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   516
		nullable := false.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   517
		(aFirstDictionary at: parser) do: [ :each |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   518
			each isNullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   519
				ifTrue: [ nullable := true ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   520
				ifFalse: [ aSet add: each ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   521
		nullable
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   522
			ifFalse: [ ^ self ] ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   523
	aSet add: PPSentinel instance
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   524
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   525
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   526
!PPSequenceParser methodsFor:'*petitanalyzer-private'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   527
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   528
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   529
	parsers keysAndValuesDo: [ :index :parser |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   530
		| followSet firstSet |
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   531
		followSet := aFollowDictionary at: parser.
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   532
		index = parsers size
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   533
			ifTrue: [ followSet addAll: aSet ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   534
			ifFalse: [
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   535
				(self class withAll: (parsers 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   536
					copyFrom: index + 1 to: parsers size))
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   537
						firstSets: aFirstDictionary
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   538
						into: (firstSet := IdentitySet new).
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   539
				(firstSet anySatisfy: [ :each | each isNullable ])
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   540
					ifTrue: [ followSet addAll: aSet ].
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   541
				followSet addAll: (firstSet 
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   542
					reject: [ :each | each isNullable ]) ] ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   543
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   544
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   545
!PPTokenParser methodsFor:'*petitanalyzer-matching'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   546
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   547
match: aParser inContext: aDictionary seen: anIdentitySet
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   548
	^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self tokenClass = aParser tokenClass ]
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   549
! !
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   550
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   551
!stx_goodies_petitparser_analyzer class methodsFor:'documentation'!
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   552
376
a2656b27cace Added monticelloName to package definition to ease export to .mcz
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 284
diff changeset
   553
extensionsVersion_HG
a2656b27cace Added monticelloName to package definition to ease export to .mcz
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 284
diff changeset
   554
a2656b27cace Added monticelloName to package definition to ease export to .mcz
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 284
diff changeset
   555
    ^ '$Changeset: <not expanded> $'
262
Claus Gittinger <cg@exept.de>
parents: 261
diff changeset
   556
! !