PPParser.st
changeset 173 44b2dcba820e
parent 126 558e35a13ce8
child 366 225737f7f83f
equal deleted inserted replaced
172:c446d835cbba 173:44b2dcba820e
    16 
    16 
    17 new
    17 new
    18 	^ self basicNew initialize
    18 	^ self basicNew initialize
    19 ! !
    19 ! !
    20 
    20 
       
    21 !PPParser methodsFor:'*petitanalyzer-enumerating'!
       
    22 
       
    23 allParsers
       
    24 	"Answer all the parse nodes of the receiver."
       
    25 
       
    26 	| result |
       
    27 	result := OrderedCollection new.
       
    28 	self allParsersDo: [ :parser | result addLast: parser ].
       
    29 	^ result
       
    30 !
       
    31 
       
    32 allParsersDo: aBlock
       
    33 	"Iterate over all the parse nodes of the receiver."
       
    34 
       
    35 	self allParsersDo: aBlock seen: IdentitySet new
       
    36 !
       
    37 
       
    38 allParsersDo: aBlock seen: aSet
       
    39 	"Iterate over all the parse nodes of the receiver, do not visit and follow the ones contained in aSet."
       
    40 
       
    41 	(aSet includes: self)
       
    42 		ifTrue: [ ^ self ].
       
    43 	aSet add: self.
       
    44 	aBlock value: self.
       
    45 	self children
       
    46 		do: [ :each | each allParsersDo: aBlock seen: aSet ]
       
    47 ! !
       
    48 
       
    49 !PPParser methodsFor:'*petitanalyzer-matching'!
       
    50 
       
    51 copyInContext: aDictionary
       
    52 	^ self copyInContext: aDictionary seen: IdentityDictionary new
       
    53 !
       
    54 
       
    55 copyInContext: aDictionary seen: aSeenDictionary
       
    56 	| copy |
       
    57 	aSeenDictionary 
       
    58 		at: self 
       
    59 		ifPresent: [ :value | ^ value ].
       
    60 	copy := aSeenDictionary
       
    61 		at: self
       
    62 		put: self copy.
       
    63 	copy children do: [ :each |
       
    64 		copy
       
    65 			replace: each
       
    66 			with: (each copyInContext: aDictionary seen: aSeenDictionary) ].
       
    67 	^ copy
       
    68 !
       
    69 
       
    70 match: aParser inContext: aDictionary
       
    71 	^ self match: aParser inContext: aDictionary seen: IdentitySet new
       
    72 !
       
    73 
       
    74 match: aParser inContext: aDictionary seen: anIdentitySet
       
    75 	"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."
       
    76 
       
    77 	(self == aParser or: [ anIdentitySet includes: self ])
       
    78 		ifTrue: [ ^ true ].
       
    79 	anIdentitySet add: self.
       
    80 	^ self class = aParser class and: [ self matchList: self children against: aParser children inContext: aDictionary seen: anIdentitySet ]
       
    81 !
       
    82 
       
    83 matchList: matchList against: parserList inContext: aDictionary seen: aSet
       
    84 	^ self matchList: matchList index: 1 against: parserList index: 1 inContext: aDictionary seen: aSet
       
    85 !
       
    86 
       
    87 matchList: matchList index: matchIndex against: parserList index: parserIndex inContext: aDictionary seen: aSet
       
    88 	| parser currentIndex currentDictionary currentSeen parsers |
       
    89 	matchList size < matchIndex
       
    90 		ifTrue: [ ^ parserList size < parserIndex ].
       
    91 	parser := matchList at: matchIndex.
       
    92 	parser class = PPListPattern ifTrue: [
       
    93 		currentIndex := parserIndex - 1.
       
    94 		[ currentDictionary := aDictionary copy.
       
    95 		currentSeen := aSet copy.
       
    96 		parserList size < currentIndex or: [ 
       
    97 			parsers := parserList copyFrom: parserIndex to: currentIndex.
       
    98 			(currentDictionary at: parser ifAbsentPut: [ parsers ]) = parsers and: [ 
       
    99 				(self
       
   100 					matchList: matchList
       
   101 					index: matchIndex + 1
       
   102 					against: parserList
       
   103 					index: currentIndex + 1
       
   104 					inContext: currentDictionary
       
   105 					seen: currentSeen)
       
   106 					ifTrue: [ 
       
   107 						currentDictionary keysAndValuesDo: [ :key :value | aDictionary at: key put: value ].
       
   108 						^ true ].
       
   109 				false ] ] ] whileFalse: [ currentIndex := currentIndex + 1 ].
       
   110 		^ false ].
       
   111 	parserList size < parserIndex
       
   112 		ifTrue: [ ^ false ].
       
   113 	(parser match: (parserList at: parserIndex) inContext: aDictionary seen: aSet)
       
   114 		ifFalse: [ ^ false ].
       
   115 	^ self
       
   116 		matchList: matchList
       
   117 		index: matchIndex + 1
       
   118 		against: parserList
       
   119 		index: parserIndex + 1
       
   120 		inContext: aDictionary
       
   121 		seen: aSet
       
   122 ! !
       
   123 
       
   124 !PPParser methodsFor:'*petitanalyzer-named'!
       
   125 
       
   126 allNamedParsers
       
   127 	"Answer all the named parse nodes of the receiver."
       
   128 
       
   129 	| result |
       
   130 	result := OrderedCollection new.
       
   131 	self allNamedParsersDo: [ :parser | result addLast: parser ].
       
   132 	^ result
       
   133 !
       
   134 
       
   135 allNamedParsersDo: aBlock
       
   136 	"Iterate over all the named parse nodes of the receiver."
       
   137 
       
   138 	self allParsersDo: [ :each | 
       
   139 		each name notNil
       
   140 			ifTrue: [ aBlock value: each ] ]
       
   141 !
       
   142 
       
   143 innerChildren
       
   144 	"Answer the inner children of the receiver."
       
   145 
       
   146 	| result |
       
   147 	result := OrderedCollection new.
       
   148 	self innerChildrenDo: [ :parser | result addLast: parser ].
       
   149 	^ result
       
   150 !
       
   151 
       
   152 innerChildrenDo: aBlock
       
   153 	"Iterate over the inner children of the receiver."
       
   154 
       
   155 	self innerChildrenDo: aBlock seen: IdentitySet new
       
   156 !
       
   157 
       
   158 innerChildrenDo: aBlock seen: aSet
       
   159 	"Iterate over the inner children of the receiver."
       
   160 	
       
   161 	self children do: [ :each |
       
   162 		(aSet includes: each)
       
   163 			ifTrue: [ ^ self ].
       
   164 		aSet add: each.
       
   165 		each name isNil ifTrue: [
       
   166 			aBlock value: each.
       
   167 			each innerChildrenDo: aBlock seen: aSet ] ]
       
   168 !
       
   169 
       
   170 namedChildren
       
   171 	"Answer the named children of the receiver."
       
   172 
       
   173 	| result |
       
   174 	result := OrderedCollection new.
       
   175 	self namedChildrenDo: [ :parser | result addLast: parser ].
       
   176 	^ result
       
   177 !
       
   178 
       
   179 namedChildrenDo: aBlock
       
   180 	"Iterate over the named children of the receiver."
       
   181 
       
   182 	self namedChildrenDo: aBlock seen: IdentitySet new
       
   183 !
       
   184 
       
   185 namedChildrenDo: aBlock seen: aSet
       
   186 	"Iterate over the named children of the receiver."
       
   187 	
       
   188 	self children do: [ :each |
       
   189 		(aSet includes: each)
       
   190 			ifTrue: [ ^ self ].
       
   191 		aSet add: each.
       
   192 		each name isNil
       
   193 			ifTrue: [ each namedChildrenDo: aBlock seen: aSet ]
       
   194 			ifFalse: [ aBlock value: each ] ]
       
   195 ! !
       
   196 
       
   197 !PPParser methodsFor:'*petitanalyzer-private'!
       
   198 
       
   199 cycleSet: aDictionary
       
   200 	"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."
       
   201 
       
   202 	^ self children
       
   203 !
       
   204 
       
   205 cycleSet: aStack firstSets: aDictionary into: aSet
       
   206 	"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."
       
   207 
       
   208 	| index |
       
   209 	self isTerminal
       
   210 		ifTrue: [ ^ self ].	
       
   211 	(index := aStack indexOf: self) > 0
       
   212 		ifTrue: [ ^ aSet addAll: (aStack copyFrom: index to: aStack size) ].
       
   213 	aStack addLast: self.
       
   214 	(self cycleSet: aDictionary)
       
   215 		do: [ :each | each cycleSet: aStack firstSets: aDictionary into: aSet ].
       
   216 	aStack removeLast
       
   217 !
       
   218 
       
   219 firstSets: aFirstDictionary into: aSet
       
   220 	"PRIVATE: Try to add additional elements to the first-set aSet of the receiver, use the incomplete aFirstDictionary."
       
   221 
       
   222 	self children do: [ :parser | aSet addAll: (aFirstDictionary at: parser) ]
       
   223 !
       
   224 
       
   225 followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet
       
   226 	"PRIVATE: Try to add additional elements to the follow-set aSet of the receiver, use the incomplete aFollowDictionary and the complete aFirstDictionary."
       
   227 	
       
   228 	self children do: [ :parser | (aFollowDictionary at: parser) addAll: aSet ]
       
   229 ! !
       
   230 
       
   231 !PPParser methodsFor:'*petitanalyzer-querying'!
       
   232 
       
   233 cycleSet
       
   234 	"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."
       
   235 	
       
   236 	| cycles |
       
   237 	cycles := IdentitySet new.
       
   238 	self cycleSet: OrderedCollection new firstSets: self firstSets into: cycles.
       
   239 	^ cycles
       
   240 !
       
   241 
       
   242 firstSet
       
   243 	"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."
       
   244 	
       
   245 	^ self firstSets at: self
       
   246 !
       
   247 
       
   248 firstSets
       
   249 	"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."
       
   250 	
       
   251 	| firstSets |
       
   252 	firstSets := IdentityDictionary new.
       
   253 	self allParsersDo: [ :each |
       
   254 		firstSets at: each put: (each isTerminal
       
   255 			ifTrue: [ IdentitySet with: each ]
       
   256 			ifFalse: [ IdentitySet new ]).
       
   257 		each isNullable
       
   258 			ifTrue: [ (firstSets at: each) add: PPSentinel instance ] ].
       
   259 	[	| changed tally |
       
   260 		changed := false.
       
   261 		firstSets keysAndValuesDo: [ :parser :first |
       
   262 			tally := first size.
       
   263 			parser firstSets: firstSets into: first.
       
   264 			changed := changed or: [ tally ~= first size ] ].
       
   265 		changed ] whileTrue.
       
   266 	^ firstSets
       
   267 !
       
   268 
       
   269 followSet
       
   270 	"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."
       
   271 
       
   272 	^ self followSets at: self
       
   273 !
       
   274 
       
   275 followSets
       
   276 	"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."
       
   277 	
       
   278 	| current previous continue firstSets followSets |
       
   279 	current := previous := 0.
       
   280 	firstSets := self firstSets.
       
   281 	followSets := IdentityDictionary new.
       
   282 	self allParsersDo: [ :each | followSets at: each put: IdentitySet new ].
       
   283 	(followSets at: self) add: PPSentinel instance.
       
   284 	[	followSets keysAndValuesDo: [ :parser :follow |
       
   285 			parser 
       
   286 				followSets: followSets
       
   287 				firstSets: firstSets
       
   288 				into: follow ].
       
   289 		current := followSets
       
   290 			inject: 0
       
   291 			into: [ :result :each | result + each size ].
       
   292 		continue := previous < current.
       
   293 		previous := current.
       
   294 		continue ] whileTrue.
       
   295 	^ followSets
       
   296 ! !
       
   297 
       
   298 !PPParser methodsFor:'*petitanalyzer-testing'!
       
   299 
       
   300 isNullable
       
   301 	"Answer true if the receiver is a nullable parser, e.g. it can successfully parse nothing."
       
   302 	
       
   303 	^ false
       
   304 !
       
   305 
       
   306 isTerminal
       
   307 	"Answer true if the receiver is a terminal or leaf parser, that means it does not delegate to any other parser."
       
   308 
       
   309 	^ self children isEmpty
       
   310 ! !
       
   311 
       
   312 !PPParser methodsFor:'*petitanalyzer-transforming'!
       
   313 
       
   314 replace: aParser with: anotherParser
       
   315 	"Replace the references of the receiver pointing to aParser with anotherParser."
       
   316 !
       
   317 
       
   318 transform: aBlock
       
   319 	"Answer a copy of all parsers reachable from the receiver transformed using aBlock."
       
   320 
       
   321 	| mapping root |
       
   322 	mapping := IdentityDictionary new.
       
   323 	self allParsersDo: [ :each |
       
   324 		mapping
       
   325 			at: each
       
   326 			put: (aBlock value: each copy) ].
       
   327 	root := mapping at: self.
       
   328 	[	| changed |
       
   329 		changed := false.
       
   330 		root allParsersDo: [ :each |
       
   331 			each children do: [ :old |
       
   332 				mapping at: old ifPresent: [ :new |
       
   333 					each replace: old with: new.
       
   334 					changed := true ] ] ].
       
   335 		changed ] whileTrue.
       
   336 	^ root
       
   337 ! !
       
   338 
    21 !PPParser methodsFor:'accessing'!
   339 !PPParser methodsFor:'accessing'!
    22 
   340 
    23 children
   341 children
    24 	"Answer a set of child parsers that could follow the receiver."
   342 	"Answer a set of child parsers that could follow the receiver."
    25 
   343 
    88 ! !
   406 ! !
    89 
   407 
    90 !PPParser methodsFor:'converting'!
   408 !PPParser methodsFor:'converting'!
    91 
   409 
    92 asParser
   410 asParser
       
   411 	"Answer the receiving parser."
       
   412 	
    93 	^ self
   413 	^ self
    94 ! !
   414 ! !
    95 
   415 
    96 !PPParser methodsFor:'copying'!
   416 !PPParser methodsFor:'copying'!
    97 
   417 
   135 	"Answer a new parser that succeeds at the end of the input and return the result of the receiver."
   455 	"Answer a new parser that succeeds at the end of the input and return the result of the receiver."
   136 
   456 
   137 	^ PPEndOfInputParser on: self
   457 	^ PPEndOfInputParser on: self
   138 !
   458 !
   139 
   459 
   140 max: anInteger
       
   141 	"Answer a new parser that parses the receiver at most anInteger times."
       
   142 	
       
   143 	^ PPRepeatingParser on: self max: anInteger
       
   144 !
       
   145 
       
   146 memoized
   460 memoized
   147 	"Answer a new memoized parser, for refraining redundant computations. This ensures polynomial time O(n^4) for left-recursive grammars and O(n^3) for non left-recursive grammars in the worst case. Not necessary for most grammars that are carefully written and in O(n) anyway."
   461 	"Answer a new memoized parser, for refraining redundant computations. This ensures polynomial time O(n^4) for left-recursive grammars and O(n^3) for non left-recursive grammars in the worst case. Not necessary for most grammars that are carefully written and in O(n) anyway."
   148 	
   462 	
   149 	^ PPMemoizedParser on: self
   463 	^ PPMemoizedParser on: self
   150 !
       
   151 
       
   152 min: anInteger
       
   153 	"Answer a new parser that parses the receiver at least anInteger times."
       
   154 	
       
   155 	^ PPRepeatingParser on: self min: anInteger
       
   156 !
       
   157 
       
   158 min: aMinInteger max: aMaxInteger
       
   159 	"Answer a new parser that parses the receiver at least aMinInteger and at most aMaxInteger times."
       
   160 	
       
   161 	^ PPRepeatingParser on: self min: aMinInteger max: aMaxInteger
       
   162 !
   464 !
   163 
   465 
   164 negate
   466 negate
   165         "Answer a new parser consumes any input token but the receiver."
   467         "Answer a new parser consumes any input token but the receiver."
   166         
   468         
   175 
   477 
   176 optional
   478 optional
   177 	"Answer a new parser that parses the receiver, if possible."
   479 	"Answer a new parser that parses the receiver, if possible."
   178 
   480 
   179 	^ PPOptionalParser on: self
   481 	^ PPOptionalParser on: self
   180 !
       
   181 
       
   182 plus
       
   183 	"Answer a new parser that parses the receiver one or more times."
       
   184 
       
   185 	^ self min: 1
       
   186 !
       
   187 
       
   188 plusGreedy: aParser
       
   189 	"Answer a new parser that parses the receiver one or more times until it reaches aParser. This is a greedy non-blind implementation of the star operator. aParser is not consumed."
       
   190 	
       
   191 	^ self , (self starGreedy: aParser) map: [ :first :rest | rest copyWithFirst: first ]
       
   192 !
       
   193 
       
   194 plusLazy: aParser
       
   195 	"Answer a new parser that parses the receiver one or more times until it reaches aParser. This is a lazy non-blind implementation of the star operator. aParser is not consumed."
       
   196 	
       
   197 	^ self , (self starLazy: aParser) map: [ :first :rest | rest copyWithFirst: first ]
       
   198 !
       
   199 
       
   200 star
       
   201 	"Answer a new parser that parses the receiver zero or more times. This is a greedy and blind implementation that tries to consume as much input as possible and it does not consider what comes afterwards."
       
   202 
       
   203 	^ PPRepeatingParser on: self
       
   204 !
       
   205 
       
   206 starGreedy: aParser
       
   207 	"Answer a new parser that parses the receiver zero or more times until it reaches aParser. This is a greedy non-blind implementation of the star operator. aParser is not consumed."
       
   208 	
       
   209 	| parser |
       
   210 	parser := PPChoiceParser new.
       
   211 	parser setParsers: (Array
       
   212 		with: (self , parser map: [ :each :rest | rest addFirst: each; yourself ])
       
   213 		with: (aParser and ==> [ :each | OrderedCollection new ])).
       
   214 	^ parser ==> [ :rest | rest asArray ]
       
   215 !
       
   216 
       
   217 starLazy: aParser
       
   218 	"Answer a new parser that parses the receiver zero or more times until it reaches aParser. This is a lazy non-blind implementation of the star operator. aParser is not consumed."
       
   219 	
       
   220 	| parser |
       
   221 	parser := PPChoiceParser new.
       
   222 	parser setParsers: (Array
       
   223 		with: (aParser and ==> [ :each | OrderedCollection new ])
       
   224 		with: (self , parser map: [ :each :rest | rest addFirst: each; yourself ])).
       
   225 	^ parser ==> [ :rest | rest asArray ]
       
   226 !
   482 !
   227 
   483 
   228 times: anInteger
   484 times: anInteger
   229 	"Answer a new parser that parses the receiver exactly anInteger times."
   485 	"Answer a new parser that parses the receiver exactly anInteger times."
   230 	
   486 	
   290 	"Answer a new parser that flattens the underlying collection."
   546 	"Answer a new parser that flattens the underlying collection."
   291 	
   547 	
   292 	^ PPFlattenParser on: self
   548 	^ PPFlattenParser on: self
   293 !
   549 !
   294 
   550 
       
   551 token
       
   552 	"Answer a new parser that transforms the input to a token."
       
   553 	
       
   554 	^ PPTokenParser on: self
       
   555 !
       
   556 
       
   557 token: aTokenClass
       
   558 	"Answer a new parser that transforms the input to a token of class aTokenClass."
       
   559 	
       
   560 	^ self token tokenClass: aTokenClass
       
   561 !
       
   562 
       
   563 trim
       
   564 	"Answer a new parser that consumes spaces before and after the receiving parser."
       
   565 	
       
   566 	^ self trimSpaces
       
   567 ! !
       
   568 
       
   569 !PPParser methodsFor:'operators-convenience'!
       
   570 
       
   571 withoutSeparators
       
   572 	"Filters out the separators from a parse result produced by one of the productions #delimitedBy: or #separatedBy:."
       
   573 	
       
   574 	^ self ==> [ :items |
       
   575 		| result |
       
   576 		result := Array new: items size + 1 // 2.
       
   577 		1 to: result size do: [ :index | result at: index put: (items at: 2 * index - 1) ].
       
   578 		result ]
       
   579 ! !
       
   580 
       
   581 !PPParser methodsFor:'operators-mapping'!
       
   582 
   295 foldLeft: aBlock
   583 foldLeft: aBlock
   296 	"Answer a new parser that that folds the result of the receiver from left-to-right into aBlock. The argument aBlock must take two or more arguments."
   584 	"Answer a new parser that that folds the result of the receiver from left-to-right into aBlock. The argument aBlock must take two or more arguments."
   297 	
   585 	
   298 	| size args |
   586 	| size args |
   299 	size := aBlock numArgs.
   587 	size := aBlock numArgs.
   300 	args := Array new: size.
   588 	args := Array new: size.
   301 	^ self ==> [ :nodes |
   589 	^ self ==> [ :nodes |
   302 		args at: 1 put: (nodes at: 1).
   590 		args at: 1 put: nodes first.
   303 		2 to: nodes size by: size - 1 do: [ :index |
   591 		2 to: nodes size by: size - 1 do: [ :index |
   304 			args
   592 			args
   305 				replaceFrom: 2 to: size with: nodes startingAt: index;
   593 				replaceFrom: 2 to: size with: nodes startingAt: index;
   306 				at: 1 put: (aBlock valueWithArguments: args) ].
   594 				at: 1 put: (aBlock valueWithArguments: args) ].
   307 		args at: 1 ]
   595 		args first ]
   308 !
   596 !
   309 
   597 
   310 foldRight: aBlock
   598 foldRight: aBlock
   311 	"Answer a new parser that that folds the result of the receiver from right-to-left into aBlock. The argument aBlock must take two or more arguments."
   599 	"Answer a new parser that that folds the result of the receiver from right-to-left into aBlock. The argument aBlock must take two or more arguments."
   312 
   600 
   313 	| size args |
   601 	| size args |
   314 	size := aBlock numArgs.
   602 	size := aBlock numArgs.
   315 	args := Array new: size.
   603 	args := Array new: size.
   316 	^ self ==> [ :nodes |
   604 	^ self ==> [ :nodes |
   317 		args at: size put: (nodes at: nodes size).
   605 		args at: size put: nodes last.
   318 		nodes size - size + 1 to: 1 by: 1 - size do: [ :index |
   606 		nodes size - size + 1 to: 1 by: 1 - size do: [ :index |
   319 			args
   607 			args
   320 				replaceFrom: 1 to: size - 1 with: nodes startingAt: index;
   608 				replaceFrom: 1 to: size - 1 with: nodes startingAt: index;
   321 				at: size put: (aBlock valueWithArguments: args) ].
   609 				at: size put: (aBlock valueWithArguments: args) ].
   322 		args at: size ]
   610 		args at: size ]
   323 !
   611 !
   324 
   612 
   325 map: aBlock
   613 map: aBlock
   326 	"Answer a new parser that works on the receiving sequence an passes in each element as a block argument."
   614 	"Answer a new parser that works on the receiving sequence an passes in each element as a block argument."
   327 	
   615 	
   328 	^ self ==> aBlock
   616 	^ aBlock numArgs = 1
   329 !
   617 		ifTrue: [ self ==> aBlock ]
   330 
   618 		ifFalse: [ self error: aBlock numArgs asString , ' arguments expected.' ]
   331 token
   619 !
   332 	"Answer a new parser that transforms the input to a token."
   620 
   333 	
   621 trim: aParser
   334 	^ PPTokenParser on: self
   622 	"Answer a new parser that consumes and ignores aParser repeatedly before and after the receiving parser."
   335 !
   623 	
   336 
   624 	^ PPTrimmingParser on: self trimmer: aParser
   337 token: aTokenClass
       
   338 	"Answer a new parser that transforms the input to a token of class aTokenClass."
       
   339 	
       
   340 	^ self token tokenClass: aTokenClass
       
   341 !
       
   342 
       
   343 trim
       
   344 	"Answer a new parser that consumes spaces before and after the receiving parser."
       
   345 	
       
   346 	^ self trimSpaces
       
   347 !
   625 !
   348 
   626 
   349 trimBlanks
   627 trimBlanks
   350 	"Answer a new parser that consumes blanks before and after the receiving parser."
   628 	"Answer a new parser that consumes blanks before and after the receiving parser."
   351 	
   629 	
   352 	^ PPTrimmingParser on: self trimmer: #blank asParser
   630 	^ self trim: #blank asParser
   353 !
   631 !
   354 
   632 
   355 trimSpaces
   633 trimSpaces
   356 	"Answer a new parser that consumes spaces before and after the receiving parser."
   634 	"Answer a new parser that consumes spaces before and after the receiving parser."
   357 	
   635 	
   358 	^ PPTrimmingParser on: self trimmer: #space asParser
   636 	^ self trim: #space asParser
       
   637 ! !
       
   638 
       
   639 !PPParser methodsFor:'operators-repeating'!
       
   640 
       
   641 max: anInteger
       
   642 	"Answer a new parser that parses the receiver at most anInteger times."
       
   643 	
       
   644 	^ self star setMax: anInteger
       
   645 !
       
   646 
       
   647 max: anInteger greedy: aParser
       
   648 	"Answer a new parser that parses the receiver at most anInteger times until it reaches aParser. This is a greedy non-blind implementation. aParser is not consumed."
       
   649 	
       
   650 	^ (self starGreedy: aParser) setMax: anInteger
       
   651 !
       
   652 
       
   653 max: anInteger lazy: aParser
       
   654 	"Answer a new parser that parses the receiver at most anInteger times until it reaches aParser. This is a lazy non-blind implementation. aParser is not consumed."
       
   655 	
       
   656 	^ (self starLazy: aParser) setMax: anInteger
       
   657 !
       
   658 
       
   659 min: anInteger
       
   660 	"Answer a new parser that parses the receiver at least anInteger times."
       
   661 	
       
   662 	^ self star setMin: anInteger
       
   663 !
       
   664 
       
   665 min: anInteger greedy: aParser
       
   666 	"Answer a new parser that parses the receiver at least anInteger times until it reaches aParser. This is a greedy non-blind implementation. aParser is not consumed."
       
   667 	
       
   668 	^ (self starGreedy: aParser) setMin: anInteger
       
   669 !
       
   670 
       
   671 min: anInteger lazy: aParser
       
   672 	"Answer a new parser that parses the receiver at least anInteger times until it reaches aParser. This is a lazy non-blind implementation. aParser is not consumed."
       
   673 	
       
   674 	^ (self starLazy: aParser) setMin: anInteger
       
   675 !
       
   676 
       
   677 min: aMinInteger max: aMaxInteger
       
   678 	"Answer a new parser that parses the receiver at least aMinInteger and at most aMaxInteger times."
       
   679 	
       
   680 	^ self star setMin: aMinInteger; setMax: aMaxInteger
       
   681 !
       
   682 
       
   683 min: aMinInteger max: aMaxInteger greedy: aParser
       
   684 	"Answer a new parser that parses the receiver at least aMinInteger and at most aMaxInteger times until it reaches aParser. This is a greedy non-blind implementation. aParser is not consumed."
       
   685 	
       
   686 	^ (self starGreedy: aParser) setMin: aMinInteger; setMax: aMaxInteger
       
   687 !
       
   688 
       
   689 min: aMinInteger max: aMaxInteger lazy: aParser
       
   690 	"Answer a new parser that parses the receiver at least aMinInteger and at most aMaxInteger times until it reaches aParser. This is a greedy non-blind implementation. aParser is not consumed."
       
   691 	
       
   692 	^ (self starLazy: aParser) setMin: aMinInteger; setMax: aMaxInteger
       
   693 !
       
   694 
       
   695 plus
       
   696 	"Answer a new parser that parses the receiver one or more times."
       
   697 
       
   698 	^ self star setMin: 1
       
   699 !
       
   700 
       
   701 plusGreedy: aParser
       
   702 	"Answer a new parser that parses the receiver one or more times until it reaches aParser. This is a greedy non-blind implementation of the star operator. aParser is not consumed."
       
   703 	
       
   704 	^ (self starGreedy: aParser) setMin: 1
       
   705 !
       
   706 
       
   707 plusLazy: aParser
       
   708 	"Answer a new parser that parses the receiver one or more times until it reaches aParser. This is a lazy non-blind implementation of the star operator. aParser is not consumed."
       
   709 	
       
   710 	^ (self starLazy: aParser) setMin: 1
       
   711 !
       
   712 
       
   713 star
       
   714 	"Answer a new parser that parses the receiver zero or more times. This is a greedy and blind implementation that tries to consume as much input as possible and it does not consider what comes afterwards."
       
   715 
       
   716 	^ PPPossessiveRepeatingParser on: self
       
   717 !
       
   718 
       
   719 starGreedy: aParser
       
   720 	"Answer a new parser that parses the receiver zero or more times until it reaches aParser. This is a greedy non-blind implementation of the star operator. aParser is not consumed."
       
   721 	
       
   722 	^ PPGreedyRepeatingParser on: self limit: aParser
       
   723 !
       
   724 
       
   725 starLazy: aParser
       
   726 	"Answer a new parser that parses the receiver zero or more times until it reaches aParser. This is a lazy non-blind implementation of the star operator. aParser is not consumed."
       
   727 	
       
   728 	^ PPLazyRepeatingParser on: self limit: aParser
   359 ! !
   729 ! !
   360 
   730 
   361 !PPParser methodsFor:'parsing'!
   731 !PPParser methodsFor:'parsing'!
   362 
   732 
   363 matches: anObject
   733 matches: anObject
   365 	
   735 	
   366 	^ (self parse: anObject) isPetitFailure not
   736 	^ (self parse: anObject) isPetitFailure not
   367 !
   737 !
   368 
   738 
   369 matchesIn: anObject
   739 matchesIn: anObject
   370 	"Search anObject repeatedly for the matches of the receiver."
   740 	"Search anObject repeatedly for the matches of the receiver. Answered an OrderedCollection of the matched parse-trees."
   371 
   741 
   372 	| result |
   742 	| result |
   373 	result := OrderedCollection new.
   743 	result := OrderedCollection new.
   374 	self 
   744 	self 
   375 		matchesIn: anObject
   745 		matchesIn: anObject
   381 	"Search anObject repeatedly for the matches of the receiver. Evaluate aBlock for each match with the matched parse-tree as the argument. Make sure to always consume exactly one character with each step, to not miss any match."
   751 	"Search anObject repeatedly for the matches of the receiver. Evaluate aBlock for each match with the matched parse-tree as the argument. Make sure to always consume exactly one character with each step, to not miss any match."
   382 
   752 
   383 	((self and ==> aBlock , #any asParser) / #any asParser) star parse: anObject
   753 	((self and ==> aBlock , #any asParser) / #any asParser) star parse: anObject
   384 !
   754 !
   385 
   755 
       
   756 matchesSkipIn: anObject
       
   757 	"Search anObject repeatedly for the matches of the receiver. Answer an OrderedCollection of the matched parse-trees. Skip over matches."
       
   758 
       
   759 	| result |
       
   760 	result := OrderedCollection new.
       
   761 	self 
       
   762 		matchesSkipIn: anObject
       
   763 		do: [ :each | result addLast: each ].
       
   764 	^ result
       
   765 !
       
   766 
       
   767 matchesSkipIn: anObject do: aBlock
       
   768 	"Search anObject repeatedly for the matches of the receiver. Evaluate aBlock for each match with the matched parse-tree as the argument. Skip over matches."
       
   769 
       
   770 	(self ==> aBlock / #any asParser) star parse: anObject
       
   771 !
       
   772 
   386 matchingRangesIn: anObject
   773 matchingRangesIn: anObject
   387 	"Search anObject repeatedly for the matches of the receiver.  Answer an OrderedCollection of ranges of each match (index of first character to: index of last character)."
   774 	"Search anObject repeatedly for the matches of the receiver. Answer an OrderedCollection of ranges of each match (index of first character to: index of last character)."
   388 	
   775 	
   389 	| result |
   776 	| result |
   390 	result := OrderedCollection new.
   777 	result := OrderedCollection new.
   391 	self
   778 	self
   392 		matchingRangesIn: anObject
   779 		matchingRangesIn: anObject
   393 		do: [ :value | result addLast: value ].
   780 		do: [ :value | result addLast: value ].
   394 	^ result
   781 	^ result
   395 !
   782 !
   396 
   783 
   397 matchingRangesIn: anObject do: aBlock
   784 matchingRangesIn: anObject do: aBlock
   398 	"Search anObject repeatedly for the matches of the receiver.  Answer an OrderedCollection of ranges of each match (index of first character to: index of last character)."
   785 	"Search anObject repeatedly for the matches of the receiver. Evaluate aBlock with the range of each match (index of first character to: index of last character)."
       
   786 
       
   787 	self token
       
   788 		matchesIn: anObject
       
   789 		do: [ :token | aBlock value: (token start to: token stop) ]
       
   790 !
       
   791 
       
   792 matchingSkipRangesIn: anObject
       
   793 	"Search anObject repeatedly for the matches of the receiver. Skip over matches. Answer an OrderedCollection of ranges of each match (index of first character to: index of last character)."
   399 	
   794 	
   400 	| result |
   795 	| result |
   401 	result := OrderedCollection new.
   796 	result := OrderedCollection new.
   402 	[ :stream | stream position + 1 ] asParser , self , [ :stream | stream position ] asParser
   797 	self
   403 		matchesIn: anObject
   798 		matchingSkipRangesIn: anObject
   404 		do: [ :value | aBlock value: (value first to: value last) ].
   799 		do: [ :value | result addLast: value ].
   405 	^ result
   800 	^ result
       
   801 !
       
   802 
       
   803 matchingSkipRangesIn: anObject do: aBlock
       
   804 	"Search anObject repeatedly for the matches of the receiver. Skip over matches. Evaluate aBlock with the range of each match (index of first character to: index of last character)."
       
   805 	
       
   806 	self token
       
   807 		matchesSkipIn: anObject
       
   808 		do: [ :token | aBlock value: (token start to: token stop) ]
   406 !
   809 !
   407 
   810 
   408 parse: anObject
   811 parse: anObject
   409 	"Parse anObject with the receiving parser and answer the parse-result or an instance of PPFailure."
   812 	"Parse anObject with the receiving parser and answer the parse-result or an instance of PPFailure."
   410 	
   813 	
   438 		ifTrue: [ aStream print: self hash ]
   841 		ifTrue: [ aStream print: self hash ]
   439 		ifFalse: [ aStream nextPutAll: self name ]
   842 		ifFalse: [ aStream nextPutAll: self name ]
   440 !
   843 !
   441 
   844 
   442 printOn: aStream
   845 printOn: aStream
   443     PPPrinter notNil ifTrue:[
   846 	super printOn: aStream.
   444         PPPrinter new 
   847 	aStream nextPut: $(.
   445             stream: aStream ;
   848 	self printNameOn: aStream.
   446             visit: self
   849 	aStream nextPut: $)
   447     ] ifFalse:[
       
   448         super printOn: aStream.
       
   449         aStream nextPut: $(.
       
   450         self printNameOn: aStream.
       
   451         aStream nextPut: $)
       
   452     ].
       
   453 
       
   454     "Modified: / 11-01-2013 / 09:20:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   455 ! !
   850 ! !
   456 
   851 
   457 !PPParser methodsFor:'testing'!
   852 !PPParser methodsFor:'testing'!
   458 
   853 
   459 isPetitParser
   854 isPetitParser
   462 
   857 
   463 isUnresolved
   858 isUnresolved
   464 	^ false
   859 	^ false
   465 ! !
   860 ! !
   466 
   861 
   467 
       
   468 !PPParser class methodsFor:'documentation'!
   862 !PPParser class methodsFor:'documentation'!
   469 
   863 
   470 version
   864 version
   471     ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParser.st,v 1.5 2013-01-11 12:31:10 vrany Exp $'
   865     ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParser.st,v 1.6 2014-03-04 14:33:11 cg Exp $'
   472 !
   866 !
   473 
   867 
   474 version_CVS
   868 version_CVS
   475     ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParser.st,v 1.5 2013-01-11 12:31:10 vrany Exp $'
   869     ^ '$Header: /cvs/stx/stx/goodies/petitparser/PPParser.st,v 1.6 2014-03-04 14:33:11 cg Exp $'
   476 !
   870 !
   477 
   871 
   478 version_SVN
   872 version_SVN
   479     ^ '§Id: PPParser.st 2 2010-12-17 18:44:23Z vranyj1 §'
   873     ^ '$Id: PPParser.st,v 1.6 2014-03-04 14:33:11 cg Exp $'
   480 ! !
   874 ! !
       
   875