3 PPDelegateParser subclass:#PPCompositeParser |
3 PPDelegateParser subclass:#PPCompositeParser |
4 instanceVariableNames:'' |
4 instanceVariableNames:'' |
5 classVariableNames:'' |
5 classVariableNames:'' |
6 poolDictionaries:'' |
6 poolDictionaries:'' |
7 category:'PetitParser-Tools' |
7 category:'PetitParser-Tools' |
8 ! |
|
9 |
|
10 PPCompositeParser comment:'A PPCompositeParser is composed parser built from various primitive parsers. |
|
11 Every production in the receiver is specified as a method that returns its parser. Note that every production requires an instance variable of the same name, otherwise the production is not cached and cannot be used in recursive grammars. Productions should refer to each other by reading the respective inst-var. Note: these inst-vars are typically not written, as the assignment happens in the initialize method using reflection. |
|
12 The start production is defined in the method start. It is aliased to the inst-var parser defined in the superclass of PPCompositeParser.' |
|
13 ! |
8 ! |
14 |
9 |
15 |
10 |
16 !PPCompositeParser class methodsFor:'instance creation'! |
11 !PPCompositeParser class methodsFor:'instance creation'! |
17 |
12 |
61 |
56 |
62 !PPCompositeParser methodsFor:'accessing'! |
57 !PPCompositeParser methodsFor:'accessing'! |
63 |
58 |
64 start |
59 start |
65 "Answer the production to start this parser with." |
60 "Answer the production to start this parser with." |
66 |
61 |
67 self subclassResponsibility |
62 self subclassResponsibility |
68 ! ! |
63 ! ! |
69 |
64 |
70 !PPCompositeParser methodsFor:'initialization'! |
65 !PPCompositeParser methodsFor:'initialization'! |
71 |
66 |
72 initializeStartingAt: aSymbol |
67 initializeStartingAt: aSymbol |
73 | allVariableNames ignoredVariableNames productionIndexesAndNames | |
68 | allVariableNames ignoredVariableNames productionIndexesAndNames | |
74 self initialize. |
69 self initialize. |
75 |
70 |
76 "find all the productions that need to be initialized" |
71 "find all the productions that need to be initialized" |
77 allVariableNames := self class allInstVarNames |
72 allVariableNames := self class allInstVarNames |
78 collect: [ :each | each asSymbol ]. |
73 collect: [ :each | each asSymbol ]. |
79 ignoredVariableNames := self class ignoredNames |
74 ignoredVariableNames := self class ignoredNames |
80 collect: [ :each | each asSymbol ]. |
75 collect: [ :each | each asSymbol ]. |
81 productionIndexesAndNames := ((1 to: self class instSize) |
76 productionIndexesAndNames := ((1 to: self class instSize) |
82 collect: [ :index | index -> (allVariableNames at: index) ]) |
77 collect: [ :index | index -> (allVariableNames at: index) ]) |
83 reject: [ :assoc | ignoredVariableNames includes: assoc value ]. |
78 reject: [ :assoc | ignoredVariableNames includes: assoc value ]. |
84 |
79 |
85 "initialize productions with an undefined parser to be replaced later" |
80 "initialize productions with an undefined parser to be replaced later" |
86 parser := PPUnresolvedParser named: aSymbol. |
81 parser := PPUnresolvedParser named: aSymbol. |
87 productionIndexesAndNames do: [ :assoc | |
82 productionIndexesAndNames do: [ :assoc | |
88 self instVarAt: assoc key put: (PPUnresolvedParser named: assoc value) ]. |
83 self instVarAt: assoc key put: (PPUnresolvedParser named: assoc value) ]. |
89 parser def: (self perform: aSymbol). |
84 parser def: (self perform: aSymbol). |
90 |
85 |
91 "resolve unresolved parsers with their actual implementation" |
86 "resolve unresolved parsers with their actual implementation" |
92 productionIndexesAndNames do: [ :assoc | |
87 productionIndexesAndNames do: [ :assoc | |
93 (self respondsTo: assoc value) |
88 (self respondsTo: assoc value) |
94 ifFalse: [ self error: 'Unable to initialize ' , assoc value printString ] |
89 ifFalse: [ self error: 'Unable to initialize ' , assoc value printString ] |
95 ifTrue: [ (self instVarAt: assoc key) def: (self perform: assoc value) ] ] |
90 ifTrue: [ (self instVarAt: assoc key) def: (self perform: assoc value) ] ] |
97 |
92 |
98 !PPCompositeParser methodsFor:'querying'! |
93 !PPCompositeParser methodsFor:'querying'! |
99 |
94 |
100 productionAt: aSymbol |
95 productionAt: aSymbol |
101 "Answer the production named aSymbol." |
96 "Answer the production named aSymbol." |
102 |
97 |
103 ^ self productionAt: aSymbol ifAbsent: [ nil ] |
98 ^ self productionAt: aSymbol ifAbsent: [ nil ] |
104 ! |
99 ! |
105 |
100 |
106 productionAt: aSymbol ifAbsent: aBlock |
101 productionAt: aSymbol ifAbsent: aBlock |
107 "Answer the production named aSymbol, if there is no such production answer the result of evaluating aBlock." |
102 "Answer the production named aSymbol, if there is no such production answer the result of evaluating aBlock." |
108 |
103 |
109 (self class ignoredNames includes: aSymbol asString) |
104 (self class ignoredNames includes: aSymbol asString) |
110 ifTrue: [ ^ aBlock value ]. |
105 ifTrue: [ ^ aBlock value ]. |
111 (self class startSymbol = aSymbol) |
106 (self class startSymbol = aSymbol) |
112 ifTrue: [ ^ parser ]. |
107 ifTrue: [ ^ parser ]. |
113 ^ self instVarAt: (self class allInstVarNames |
108 ^ self instVarAt: (self class allInstVarNames |