|
1 "{ Package: 'stx:goodies/petitparser/compiler' }" |
|
2 |
|
3 PPCListNode subclass:#PPCSequenceNode |
|
4 instanceVariableNames:'' |
|
5 classVariableNames:'' |
|
6 poolDictionaries:'' |
|
7 category:'PetitCompiler-Nodes' |
|
8 ! |
|
9 |
|
10 PPCSequenceNode comment:'' |
|
11 ! |
|
12 |
|
13 !PPCSequenceNode methodsFor:'accessing'! |
|
14 |
|
15 prefix |
|
16 ^ #seq |
|
17 ! ! |
|
18 |
|
19 !PPCSequenceNode methodsFor:'analysis'! |
|
20 |
|
21 acceptsEpsilon |
|
22 ^ self acceptsEpsilonOpenSet: IdentitySet new. |
|
23 ! |
|
24 |
|
25 acceptsEpsilonOpenSet: set |
|
26 set add: self. |
|
27 ^ self children allSatisfy: [:e | e acceptsEpsilonOpenSet: set ] |
|
28 ! |
|
29 |
|
30 firstSetSuchThat: block into: aCollection openSet: aSet |
|
31 (aSet includes: self) ifTrue: [ ^ aCollection ]. |
|
32 aSet add: self. |
|
33 |
|
34 (block value: self) ifTrue: [ aCollection add: self. ^ aCollection ]. |
|
35 |
|
36 self children do: [ :child | |
|
37 child firstSetSuchThat: block into: aCollection openSet: aSet. |
|
38 child acceptsEpsilon ifFalse: [ ^ aCollection ] |
|
39 ]. |
|
40 ^ aCollection |
|
41 ! ! |
|
42 |
|
43 !PPCSequenceNode methodsFor:'compiling'! |
|
44 |
|
45 addGuard: compiler id: id |
|
46 | guard firsts | |
|
47 (compiler guards not or: [(guard := PPCGuard on: self) makesSense not]) ifTrue: [ ^ self]. |
|
48 |
|
49 firsts := (self firstSetSuchThat: [ :e | (e isKindOf: PPCTrimmingTokenNode) or: [ e isTerminal ] ]). |
|
50 |
|
51 |
|
52 (firsts allSatisfy: [ :e | e isKindOf: PPCTrimmingTokenNode ]) ifTrue: [ |
|
53 "If we start with trimming, we should invoke the whitespace parser" |
|
54 firsts anyOne compileWhitespace: compiler. |
|
55 |
|
56 compiler add: 'context atEnd ifTrue: [ ^ self error ].'. |
|
57 guard id: id, '_guard'. |
|
58 guard compileGuard: compiler. |
|
59 compiler addOnLine: 'ifFalse: [ ^ self error ].' |
|
60 ]. |
|
61 |
|
62 (firsts allSatisfy: [ :e | e isTerminal ]) ifTrue: [ |
|
63 compiler add: 'context atEnd ifTrue: [ ^ self error ].'. |
|
64 guard id: id, '_guard'. |
|
65 guard compileGuard: compiler. |
|
66 compiler addOnLine: 'ifFalse: [ ^ self error ].' |
|
67 ]. |
|
68 ! |
|
69 |
|
70 compileWith: compiler effect: effect id: id |
|
71 compiler startMethod: id. |
|
72 compiler addVariable: 'retval'. |
|
73 compiler addVariable: 'element'. |
|
74 compiler addVariable: 'memento'. |
|
75 compiler add: (compiler smartRemember: self). |
|
76 compiler add: 'retval := Array new: ', children size asString, '.'. |
|
77 self addGuard: compiler id: id. |
|
78 |
|
79 (1 to: children size) do: [ :idx | |child| |
|
80 child := children at: idx. |
|
81 compiler add: 'element := '. |
|
82 compiler callOnLine: (child compileWith: compiler). |
|
83 |
|
84 compiler add: 'error ifTrue: [ ', (compiler smartRestore: self) ,' ^ failure ].'. |
|
85 compiler add: 'retval at: ', idx asString, ' put: element.'. |
|
86 ]. |
|
87 compiler add: '^ retval'. |
|
88 ^ compiler stopMethod. |
|
89 ! ! |
|
90 |
|
91 !PPCSequenceNode methodsFor:'optimizing'! |
|
92 |
|
93 asFast |
|
94 ^ PPCTokenSequenceNode new |
|
95 children: children; |
|
96 name: self name; |
|
97 yourself |
|
98 ! ! |
|
99 |