1818 * specific language governing permissions and limitations
1919 * under the License.
2020 */
21- package com .igormaznitsa .prologparser . tokenizer ;
21+ package com .igormaznitsa .prologparser ;
2222
23- import com .igormaznitsa .prologparser .PrologParser ;
2423import com .igormaznitsa .prologparser .exceptions .CriticalUnexpectedError ;
2524import com .igormaznitsa .prologparser .exceptions .PrologParserException ;
2625import com .igormaznitsa .prologparser .terms .PrologAtom ;
2928import com .igormaznitsa .prologparser .terms .PrologTerm ;
3029import com .igormaznitsa .prologparser .terms .Quotation ;
3130import com .igormaznitsa .prologparser .terms .TermType ;
31+ import com .igormaznitsa .prologparser .tokenizer .Op ;
32+ import com .igormaznitsa .prologparser .tokenizer .OpAssoc ;
33+ import com .igormaznitsa .prologparser .tokenizer .TermWrapper ;
3234import com .igormaznitsa .prologparser .utils .SoftObjectPool ;
3335
3436import java .util .ArrayList ;
3537
36- public final class TreeItem {
38+ final class AstItem {
3739
38- private final SoftObjectPool <TreeItem > pool ;
40+ private final SoftObjectPool <AstItem > astItemPool ;
3941
4042 private final PrologParser parser ;
4143 private final SoftObjectPool <TermWrapper > termWrapperPool ;
42- private TreeItem leftBranch ;
43- private TreeItem rightBranch ;
44- private TreeItem parentItem ;
44+ private AstItem leftItem ;
45+ private AstItem rightItem ;
46+ private AstItem parentItem ;
4547 private PrologTerm savedTerm ;
4648
47- public TreeItem (final PrologParser parser , final SoftObjectPool <TreeItem > pool , final SoftObjectPool <TermWrapper > termWrapperPool ) {
49+ public AstItem (final PrologParser parser , final SoftObjectPool <AstItem > pool , final SoftObjectPool <TermWrapper > termWrapperPool ) {
4850 this .parser = parser ;
49- this .pool = pool ;
51+ this .astItemPool = pool ;
5052 this .termWrapperPool = termWrapperPool ;
5153 }
5254
53- public TreeItem setData (final PrologTerm term , final int line , final int pos ) {
55+ public AstItem setData (final PrologTerm term , final int line , final int pos ) {
5456 if (term == null ) {
5557 this .replaceSavedTerm (null );
5658 } else {
@@ -75,53 +77,53 @@ private void replaceSavedTerm(final PrologTerm newValue) {
7577 }
7678
7779 public void release () {
78- this .leftBranch = null ;
79- this .rightBranch = null ;
80+ this .leftItem = null ;
81+ this .rightItem = null ;
8082 this .parentItem = null ;
8183
8284 this .replaceSavedTerm (null );
8385
84- this .pool .push (this );
86+ this .astItemPool .push (this );
8587 }
8688
8789 public int getPrecedence () {
8890 return this .savedTerm .getPrecedence ();
8991 }
9092
91- public TreeItem makeAsRightBranch (final TreeItem item ) {
92- final TreeItem currentSubbranch = rightBranch ;
93+ public AstItem makeAsRightBranch (final AstItem item ) {
94+ final AstItem currentSubbranch = rightItem ;
9395 setRightBranch (item );
9496 item .setLeftBranch (currentSubbranch );
95- TreeItem result = this ;
97+ AstItem result = this ;
9698 if (item .getType () == TermType .OPERATOR && item .getPrecedence () != 0 ) {
9799 result = item ;
98100 }
99101 return result ;
100102 }
101103
102- public TreeItem makeAsOwnerWithLeftBranch (final TreeItem item ) {
104+ public AstItem makeAsOwnerWithLeftBranch (final AstItem item ) {
103105 this .replaceForOwner (item );
104106 item .setLeftBranch (this );
105107 return item ;
106108 }
107109
108- public TreeItem getRightBranch () {
109- return rightBranch ;
110+ public AstItem getRightBranch () {
111+ return rightItem ;
110112 }
111113
112- private void setRightBranch (final TreeItem item ) {
113- rightBranch = item ;
114+ private void setRightBranch (final AstItem item ) {
115+ rightItem = item ;
114116 if (item != null ) {
115117 item .parentItem = this ;
116118 }
117119 }
118120
119- private TreeItem getLeftBranch () {
120- return leftBranch ;
121+ private AstItem getLeftBranch () {
122+ return leftItem ;
121123 }
122124
123- private void setLeftBranch (final TreeItem item ) {
124- leftBranch = item ;
125+ private void setLeftBranch (final AstItem item ) {
126+ leftItem = item ;
125127 if (item != null ) {
126128 item .parentItem = this ;
127129 }
@@ -131,10 +133,10 @@ public TermType getType() {
131133 return savedTerm .getType ();
132134 }
133135
134- public TreeItem findRoot () {
135- TreeItem result = this ;
136+ public AstItem findRoot () {
137+ AstItem result = this ;
136138 while (!Thread .currentThread ().isInterrupted ()) {
137- final TreeItem theParent = result .parentItem ;
139+ final AstItem theParent = result .parentItem ;
138140 if (theParent == null ) {
139141 break ;
140142 } else {
@@ -144,11 +146,11 @@ public TreeItem findRoot() {
144146 return result ;
145147 }
146148
147- public TreeItem findFirstNodeWithSuchOrLowerPrecedence (final int precedence ) {
148- TreeItem result = this ;
149+ public AstItem findFirstNodeWithSuchOrLowerPrecedence (final int precedence ) {
150+ AstItem result = this ;
149151
150152 while (!Thread .currentThread ().isInterrupted ()) {
151- final TreeItem itsParent = result .parentItem ;
153+ final AstItem itsParent = result .parentItem ;
152154 if (itsParent == null || result .getPrecedence () >= precedence ) {
153155 break ;
154156 } else {
@@ -159,7 +161,7 @@ public TreeItem findFirstNodeWithSuchOrLowerPrecedence(final int precedence) {
159161 return result ;
160162 }
161163
162- private void replaceForOwner (final TreeItem newItem ) {
164+ private void replaceForOwner (final AstItem newItem ) {
163165 if (parentItem == null ) {
164166 newItem .parentItem = null ;
165167 return ;
@@ -181,19 +183,19 @@ private boolean isOperandsOk() {
181183 switch (wrappedOperator .getAssoc ()) {
182184 case FX :
183185 case FY :
184- return this .leftBranch == null && this .rightBranch != null ;
186+ return this .leftItem == null && this .rightItem != null ;
185187 case YF :
186188 case XF :
187- return this .leftBranch != null && this .rightBranch == null ;
189+ return this .leftItem != null && this .rightItem == null ;
188190 case XFX :
189191 case XFY :
190192 case YFX :
191- return this .leftBranch != null && this .rightBranch != null ;
193+ return this .leftItem != null && this .rightItem != null ;
192194 default :
193195 throw new CriticalUnexpectedError ();
194196 }
195197 } else {
196- return this .leftBranch == null && this .rightBranch == null ;
198+ return this .leftItem == null && this .rightItem == null ;
197199 }
198200 }
199201
@@ -203,33 +205,38 @@ private boolean isPrecedenceOk() {
203205 final Op wrappedOperator = (Op ) ((TermWrapper ) this .savedTerm ).getWrappedTerm ();
204206 switch (wrappedOperator .getAssoc ()) {
205207 case FX :
206- return this .leftBranch == null && (this .rightBranch != null && this .rightBranch .getPrecedence () < thisPrecedence );
208+ return this .leftItem == null && (this .rightItem != null && this .rightItem .getPrecedence () < thisPrecedence );
207209 case FY :
208- return this .leftBranch == null && (this .rightBranch != null && this .rightBranch .getPrecedence () <= thisPrecedence );
210+ return this .leftItem == null && (this .rightItem != null && this .rightItem .getPrecedence () <= thisPrecedence );
209211 case YF :
210- return (this .leftBranch != null && this .leftBranch .getPrecedence () <= thisPrecedence ) && this .rightBranch == null ;
212+ return (this .leftItem != null && this .leftItem .getPrecedence () <= thisPrecedence ) && this .rightItem == null ;
211213 case XF :
212- return (this .leftBranch != null && this .leftBranch .getPrecedence () < thisPrecedence ) && this .rightBranch == null ;
214+ return (this .leftItem != null && this .leftItem .getPrecedence () < thisPrecedence ) && this .rightItem == null ;
213215 case XFX :
214- return (this .leftBranch != null && this .leftBranch .getPrecedence () < thisPrecedence ) && (this .rightBranch != null && this .rightBranch .getPrecedence () < thisPrecedence );
216+ return (this .leftItem != null && this .leftItem .getPrecedence () < thisPrecedence ) && (this .rightItem != null && this .rightItem .getPrecedence () < thisPrecedence );
215217 case XFY :
216- return (this .leftBranch != null && this .leftBranch .getPrecedence () < thisPrecedence ) && (this .rightBranch != null && this .rightBranch .getPrecedence () <= thisPrecedence );
218+ return (this .leftItem != null && this .leftItem .getPrecedence () < thisPrecedence ) && (this .rightItem != null && this .rightItem .getPrecedence () <= thisPrecedence );
217219 case YFX :
218- return (this .leftBranch != null && this .leftBranch .getPrecedence () <= thisPrecedence ) && (this .rightBranch != null && this .rightBranch .getPrecedence () < thisPrecedence );
220+ return (this .leftItem != null && this .leftItem .getPrecedence () <= thisPrecedence ) && (this .rightItem != null && this .rightItem .getPrecedence () < thisPrecedence );
219221 default :
220222 throw new CriticalUnexpectedError ();
221223 }
222224 } else {
223- return this .leftBranch == null && this .rightBranch == null ;
225+ return this .leftItem == null && this .rightItem == null ;
224226 }
225227 }
226228
227- private boolean isBlock () {
229+ private boolean isAnyBlock () {
228230 return this .savedTerm .getType () == TermType .STRUCT
229231 && (this .savedTerm .getFunctor () == Op .VIRTUAL_OPERATOR_BLOCK
230232 || this .savedTerm .getFunctor () == Op .VIRTUAL_OPERATOR_CURLY_BLOCK );
231233 }
232234
235+ private boolean isBlock () {
236+ return this .savedTerm .getType () == TermType .STRUCT
237+ && this .savedTerm .getFunctor () == Op .VIRTUAL_OPERATOR_BLOCK ;
238+ }
239+
233240 private boolean isOperator () {
234241 return this .savedTerm .getType () == TermType .OPERATOR ;
235242 }
@@ -246,15 +253,15 @@ public PrologTerm convertToTermAndRelease() {
246253 switch (savedTerm .getType ()) {
247254 case OPERATOR : {
248255 final TermWrapper wrapper = (TermWrapper ) this .savedTerm ;
249- if (this .leftBranch == null && this .rightBranch == null ) {
256+ if (this .leftItem == null && this .rightItem == null ) {
250257 // it is an atom because it has not any argument
251258 return new PrologAtom (wrapper .getWrappedTerm ().getText (), wrapper .getQuotation (), wrapper .getPos (), wrapper .getLine ());
252259 }
253260
254- if (this .leftBranch == null ) {
255- if (this .rightBranch .getType () == TermType .STRUCT && this .rightBranch .savedTerm .isBlock () && !((PrologStruct ) this .rightBranch .savedTerm ).isEmpty ()) {
261+ if (this .leftItem == null ) {
262+ if (this .rightItem .getType () == TermType .STRUCT && this .rightItem .savedTerm .isAnyBlock () && !((PrologStruct ) this .rightItem .savedTerm ).isEmpty ()) {
256263
257- final PrologTerm rightTerm = this .rightBranch .convertToTermAndRelease ();
264+ final PrologTerm rightTerm = this .rightItem .convertToTermAndRelease ();
258265 Op operator = (Op ) wrapper .getWrappedTerm ();
259266 final PrologTerm blockContent = ((PrologStruct ) rightTerm ).getTermAt (0 );
260267
@@ -265,17 +272,15 @@ public PrologTerm convertToTermAndRelease() {
265272 return new PrologStruct (operator , terms , wrapper .getLine (), wrapper .getPos ());
266273 } else {
267274 final Op appropriateOperator = this .parser .getContext ().findOpForName (this .parser , operator .getText ()).findForArity (terms .length );
268-
275+
269276 if (appropriateOperator == null ) {
270- if (operator .getArity () == 1 ) {
271- return new PrologStruct (operator , new PrologTerm []{blockContent }, wrapper .getLine (), wrapper .getPos ());
272- } else {
273- return new PrologStruct (
274- new PrologAtom (wrapper .getText (), Quotation .SINGLE , wrapper .getLine (), wrapper .getPos ()),
275- terms , wrapper .getLine (), wrapper .getPos ());
276- }
277+ if (operator .getArity () == 1 ) {
278+ return new PrologStruct (operator , new PrologTerm []{blockContent }, wrapper .getLine (), wrapper .getPos ());
279+ } else {
280+ return new PrologStruct (new PrologAtom (wrapper .getText (), Quotation .SINGLE , wrapper .getLine (), wrapper .getPos ()), terms , wrapper .getLine (), wrapper .getPos ());
281+ }
277282 } else {
278- return new PrologStruct (appropriateOperator , terms , wrapper .getLine (), wrapper .getPos ());
283+ return new PrologStruct (appropriateOperator , terms , wrapper .getLine (), wrapper .getPos ());
279284 }
280285 }
281286
@@ -293,8 +298,8 @@ public PrologTerm convertToTermAndRelease() {
293298 }
294299 }
295300 }
296- } else if (this .isBlock () && this .leftBranch . isBlock ()) {
297- return this .leftBranch .convertToTermAndRelease ();
301+ } else if (this .isAnyBlock () && this .leftItem . isAnyBlock ()) {
302+ return new PrologStruct ( wrapper . getWrappedTerm (), new PrologTerm []{ this .leftItem .convertToTermAndRelease ()}, wrapper . getLine (), wrapper . getPos () );
298303 }
299304
300305 if (!isOperandsOk ()) {
@@ -305,15 +310,15 @@ public PrologTerm convertToTermAndRelease() {
305310 final PrologTerm right ;
306311
307312 if (!isPrecedenceOk ()) {
308- if (this .rightBranch != null && this .rightBranch .isOperator () && this .rightBranch .getOpAssoc ().isPrefix ()) {
309- left = this .leftBranch == null ? null : this .leftBranch .convertToTermAndRelease ();
310- right = new PrologStruct (Op .VIRTUAL_OPERATOR_BLOCK , new PrologTerm []{this .rightBranch .convertToTermAndRelease ()});
313+ if (this .rightItem != null && this .rightItem .isOperator () && this .rightItem .getOpAssoc ().isPrefix ()) {
314+ left = this .leftItem == null ? null : this .leftItem .convertToTermAndRelease ();
315+ right = new PrologStruct (Op .VIRTUAL_OPERATOR_BLOCK , new PrologTerm []{this .rightItem .convertToTermAndRelease ()});
311316 } else {
312317 throw new PrologParserException ("Operator precedence clash or missing operator: [" + wrapper .getText () + ']' , wrapper .getLine (), wrapper .getPos ());
313318 }
314319 } else {
315- left = this .leftBranch == null ? null : this .leftBranch .convertToTermAndRelease ();
316- right = this .rightBranch == null ? null : this .rightBranch .convertToTermAndRelease ();
320+ left = this .leftItem == null ? null : this .leftItem .convertToTermAndRelease ();
321+ right = this .rightItem == null ? null : this .rightItem .convertToTermAndRelease ();
317322 }
318323
319324 // this code replaces '-'(number) to '-number' if number is not negative one
@@ -338,9 +343,12 @@ public PrologTerm convertToTermAndRelease() {
338343 final PrologStruct thisStruct = (PrologStruct ) this .savedTerm ;
339344 if ((thisStruct .getFunctor () == Op .VIRTUAL_OPERATOR_BLOCK || thisStruct .getFunctor () == Op .VIRTUAL_OPERATOR_CURLY_BLOCK )
340345 && thisStruct .getArity () == 1 ) {
346+
341347 final PrologTerm thatTerm = thisStruct .getTermAt (0 );
348+
342349 if (thatTerm .getType () == TermType .STRUCT && (thatTerm .getFunctor () == Op .VIRTUAL_OPERATOR_BLOCK || thatTerm .getFunctor () == Op .VIRTUAL_OPERATOR_CURLY_BLOCK )) {
343- result = thatTerm ;
350+ // rolling normal blocks
351+ result = thatTerm .isBlock () && (this .isBlock ()&& (this .parentItem == null || (this .parentItem != null && this .parentItem .isBlock ()))) ? thatTerm : thisStruct ;
344352 } else {
345353 result = thisStruct ;
346354 }
0 commit comments