Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/sablecc/sablecc/Inlining.java


1   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2    * This file is part of SableCC.                             *
3    * See the file "LICENSE" for copyright information and the  *
4    * terms and conditions for copying, distribution and        *
5    * modification of SableCC.                                  *
6    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7   
8   package org.sablecc.sablecc;
9   
10  import java.util.*;
11  import org.sablecc.sablecc.analysis.*;
12  import org.sablecc.sablecc.node.*;
13  
14  public class Inlining
15  {
16    public static LinkedList productionsToBeRemoved =
17      new TypedLinkedList(StringCast.instance);
18  
19    private AProd current_production;
20  
21    //The production to inline within current_production
22    private In_Production prod_to_inline;
23  
24    public Inlining(AProd curr_prod, In_Production prod_to_inline)
25    {
26      this.current_production = curr_prod;
27      this.prod_to_inline = prod_to_inline;
28    }
29  
30    /*
31     * The core of inlining is done here.
32     * returns true if it succeed and false otherwise
33    */
34    public boolean inlineProduction()
35    {
36      AParsedAlt[] alts = (AParsedAlt[])current_production.getAlts().toArray(new AParsedAlt[0]);
37      final BooleanEx prodMustBeInlined = new BooleanEx(false);
38  
39      /*
40        We're trying to detect if the current production must be inlined.
41        ie one of its alternatives contains production to inline
42      */
43      for(int i=0; i<alts.length; i++)
44      {
45        ((PAlt)alts[i]).apply( new DepthFirstAdapter()
46                               {
47                                 public void caseAElem(AElem node)
48                                 {
49                                   String elem_name = node.getId().getText();
50  
51                                   if(elem_name.equals(prod_to_inline.getName()) &&
52                                       !(node.getSpecifier() instanceof ATokenSpecifier) )
53                                   {
54                                     prodMustBeInlined.setValue(true);
55                                   }
56                                 }
57                               }
58                             );
59        //We only need to know if one element within one of the production alternatives matches.
60        if(prodMustBeInlined.getValue())
61        {
62          break;
63        }
64      }
65  
66      if(prodMustBeInlined.getValue())
67      {
68        //list of productions which inlining was a success.
69        if( !productionsToBeRemoved.contains(ResolveIds.name(prod_to_inline.getName())) )
70        {
71          productionsToBeRemoved.add("P" + ResolveIds.name(prod_to_inline.getName()));
72        }
73  
74        /*
75        Once we detect that the production can be inline, 
76        we try to inline each of its alternatives.
77         */
78        LinkedList listOfAlts = new TypedLinkedList(NodeCast.instance);
79        for(int i=0; i<alts.length; i++)
80        {
81          listOfAlts.addAll( inlineAlternative(alts[i]) );
82        }
83        current_production.setAlts(listOfAlts);
84        return true;
85      }
86      return false;
87    }
88  
89    /*
90     * Inlining of an alternative
91     *
92     */
93    public LinkedList inlineAlternative(AParsedAlt alt)
94    {
95      AElem[] elems = (AElem[])alt.getElems().toArray(new AElem[0]);
96      String elem_name ;
97      LinkedList eventualProdIdOrNames = new LinkedList();
98      int occurenceNb = 0;
99  
100     for(int i=0; i<elems.length; i++)
101     {
102       elem_name = elems[i].getId().getText();
103 
104       /*
105       Element to inline within an alternative is added to
106       a list of occurrences of the production to inline
107       */
108       if(elem_name.equals(prod_to_inline.getName()) &&
109           !(elems[i].getSpecifier() instanceof ATokenSpecifier) )
110       {
111         occurenceNb++;
112         if(elems[i].getElemName() != null)
113         {
114           eventualProdIdOrNames.add( elems[i].getElemName().getText() );
115         }
116         else
117         {
118           eventualProdIdOrNames.add( elems[i].getId().getText() );
119         }
120       }
121     }
122     alt.apply(new PrettyPrinter());
123 
124     LinkedList resultingListOfAlts = new TypedLinkedList();
125     resultingListOfAlts.add(alt);
126     for(int i=0; i<occurenceNb; i++)
127     {
128       resultingListOfAlts = inline(resultingListOfAlts, i+1);
129     }
130 
131     return resultingListOfAlts;
132   }
133 
134   String alt_elem_info = null;
135   /*
136    * whichOccurence is used to number element within the alternative
137    */
138   public LinkedList inline(LinkedList altsList, int whichOccurence)
139   {
140     LinkedList resultList = new LinkedList();
141     AParsedAlt[] alts = (AParsedAlt[])altsList.toArray(new AParsedAlt[0]);
142     AParsedAlt aParsed_alt;
143     Map mapOfNewTermNames;
144 
145     for(int i=0; i<alts.length; i++)
146     {
147       aParsed_alt = alts[i];
148 
149       for(int j=0; j<prod_to_inline.getNbAlts(); j++)
150       {
151         mapOfNewTermNames = new TypedHashMap(StringCast.instance,
152                                              StringCast.instance);
153 
154         LinkedList listElems = inlineList(aParsed_alt.getElems(),
155                                           prod_to_inline.getAlternative(j).getElems(),
156                                           mapOfNewTermNames);
157         AAltTransform aAltTransform =
158           (AAltTransform)((AAltTransform)aParsed_alt.getAltTransform()).clone();
159         final Map currentMap = prod_to_inline.getAlternative(j).getProdTransform_AlTransformMap();
160 
161         aAltTransform.apply(new DepthFirstAdapter()
162                             {
163                               public void caseASimpleTerm(ASimpleTerm node)
164                               {
165                                 if(node.getId().getText().equals(alt_elem_info)  &&
166                                     !(node.getSpecifier() instanceof ATokenSpecifier) )
167                                 {
168                                   String termTail;
169                                   if(node.getSimpleTermTail() != null)
170                                   {
171                                     termTail = node.getSimpleTermTail().getText();
172                                   }
173                                   else
174                                   {
175                                     termTail = prod_to_inline.getName();
176                                   }
177 
178                                   PTerm term = (PTerm)((PTerm)currentMap.get(termTail)).clone();
179 
180                                   if(currentMap.get(termTail) != null)
181                                   {
182                                     node.replaceBy(term);
183                                   }
184                                 }
185                               }
186 
187                               public void caseASimpleListTerm(final ASimpleListTerm node_)
188                               {
189                                 if(node_.getId().getText().equals(alt_elem_info)  &&
190                                     !(node_.getSpecifier() instanceof ATokenSpecifier) )
191                                 {
192                                   String termTail;
193                                   if(node_.getSimpleTermTail() != null)
194                                   {
195                                     termTail = node_.getSimpleTermTail().getText();
196                                   }
197                                   else
198                                   {
199                                     termTail = prod_to_inline.getName();
200                                   }
201 
202                                   if(currentMap.get(termTail) != null)
203                                   {
204                                     PTerm term = (PTerm)currentMap.get(termTail);
205 
206                                     if( !(currentMap.get(termTail) instanceof ANewListTerm) &&
207                                         !(currentMap.get(termTail) instanceof ASimpleListTerm)
208                                       )
209                                     {
210                                       term.apply(new DepthFirstAdapter()
211                                                  {
212                                                    public void caseANewTerm(ANewTerm node)
213                                                    {
214                                                      node_.replaceBy( new ANewListTerm(   (AProdName)node.getProdName().clone(),
215                                                                                           (TLPar)node.getLPar().clone(),
216                                                                                           (LinkedList)cloneList(node.getParams())
217                                                                                       )
218                                                                     );
219                                                    }
220 
221                                                    public void caseASimpleTerm(ASimpleTerm node)
222                                                    {
223                                                      PSpecifier specifier = null;
224                                                      TId simpleTermTail = null;
225                                                      if(node.getSpecifier() != null)
226                                                      {
227                                                        specifier = (PSpecifier)node.getSpecifier().clone();
228                                                      }
229                                                      if(node.getSimpleTermTail() != null)
230                                                      {
231                                                        simpleTermTail = (TId)node.getSimpleTermTail().clone();
232                                                      }
233                                                      node_.replaceBy( new ASimpleListTerm(  specifier,
234                                                                                             (TId)node.getId().clone(),
235                                                                                             simpleTermTail
236                                                                                          )
237                                                                     );
238                                                    }
239 
240                                                    public void caseNullTerm(ANullTerm node)
241                                                    {
242                                                      node_.replaceBy( null );
243                                                    }
244 
245                                                    public void caseAListTerm(AListTerm node)
246                                                    {
247                                                      AListTerm parent = (AListTerm)node_.parent();
248                                                      LinkedList oldlistTerms = parent.getListTerms();
249                                                      LinkedList newlistTerms = new LinkedList();
250 
251                                                      Object[] oldListTermsArray = (Object[]) oldlistTerms.toArray();
252                                                      for(int i=0; i<oldListTermsArray.length; i++)
253                                                      {
254                                                        if(oldListTermsArray[i] != node_)
255                                                        {
256                                                          if(oldListTermsArray[i] instanceof PTerm)
257                                                          {
258                                                            newlistTerms.add( ((PTerm)oldListTermsArray[i]).clone() );
259                                                          }
260                                                          else
261                                                          {
262                                                            newlistTerms.add( ((PListTerm)oldListTermsArray[i]).clone() );
263                                                          }
264                                                        }
265                                                        else
266                                                        {
267                                                          newlistTerms.addAll(cloneList(node.getListTerms()));
268                                                        }
269                                                      }
270                                                      parent.setListTerms(newlistTerms);
271                                                    }
272                                                  }
273                                                 );
274                                     }
275                                     else
276                                     {
277                                       node_.replaceBy(term);
278                                     }
279                                   }
280                                 }
281                               }
282                             }
283                            );
284 
285         AAltTransform tmpaAltTransform = (AAltTransform)aAltTransform.clone();
286         fixSimpleTermOrSimpleListTermNames(tmpaAltTransform, mapOfNewTermNames);
287         String newAltName;
288         if(aParsed_alt.getAltName() != null)
289         {
290           newAltName = aParsed_alt.getAltName().getText()+ "$" +
291                        prod_to_inline.getAlternative(j).getName() + whichOccurence;
292         }
293         else
294         {
295           newAltName = prod_to_inline.getAlternative(j).getName() + whichOccurence;
296         }
297 
298         resultList.add( new AParsedAlt(new TId(newAltName),
299                                        listElems,
300                                        //(AAltTransform)aAltTransform.clone()
301                                        tmpaAltTransform)
302                       );
303       }
304     }
305     return resultList;
306   }
307 
308   public LinkedList inlineList(LinkedList oldElemsList,
309                                AElem[] inliningProductionsElems,
310                                Map mapOfNewTermNames)
311   {
312     int position = 0;
313     AElem[] listElems = (AElem[]) oldElemsList.toArray(new AElem[0]);
314     for(int i=0; i<listElems.length; i++)
315     {
316       if( listElems[i].getId().getText().equals(prod_to_inline.getName()) )
317       {
318         /*if( (listElems[i].getElemName() != null && listElems[i].getElemName().getText().equals(name) )
319           || listElems[i].getElemName() == null )
320           {*/
321         position = i;
322         if(listElems[i].getElemName() != null)
323         {
324           alt_elem_info = listElems[i].getElemName().getText();
325         }
326         else
327         {
328           alt_elem_info = listElems[i].getId().getText();
329         }
330         break;
331         //}
332       }
333     }
334 
335     LinkedList list = new LinkedList();
336     int elemPosition = 1;
337     for(int i=0; i<position; i++)
338     {
339       list.add(((AElem)oldElemsList.get(i)).clone() );
340     }
341 
342     for(int i=0; i<inliningProductionsElems.length; i++)
343     {
344       list.add(inliningProductionsElems[i].clone());
345     }
346 
347     for(int i=position+1; i<listElems.length; i++)
348     {
349       list.add(((AElem)oldElemsList.get(i)).clone());
350     }
351 
352     AElem[] listOfAltElems = (AElem[]) list.toArray(new AElem[0]);
353     for(int i=0; i<listOfAltElems.length; i++)
354     {
355       String old_name = listOfAltElems[i].getId().getText();
356       TId elemName = (TId)listOfAltElems[i].getElemName();
357       if(elemName != null)
358       {
359         elemName = (TId)elemName;
360         old_name = elemName.getText();
361       }
362 
363       String elemNameString = (elemName != null ? elemName.getText() : "elem" );
364       elemNameString += (i+1);
365       listOfAltElems[i].setElemName(new TId(elemNameString));
366       mapOfNewTermNames.put(old_name, elemNameString);
367     }
368 
369     return list;
370   }
371 
372   private void fixSimpleTermOrSimpleListTermNames(AAltTransform tmpaAltTransform,
373       final Map mapOldNameNewNames)
374   {
375     tmpaAltTransform.apply(new DepthFirstAdapter()
376                            {
377                              public void caseASimpleTerm(ASimpleTerm node)
378                              {
379                                if(mapOldNameNewNames.get(node.getId().getText()) != null)
380                                {
381                                  node.setId(new TId( (String)mapOldNameNewNames.get(node.getId().getText()) ));
382                                }
383                              }
384 
385                              public void caseASimpleListTerm(ASimpleListTerm node)
386                              {
387                                if(mapOldNameNewNames.get(node.getId().getText()) != null)
388                                {
389                                  node.setId(new TId( (String)mapOldNameNewNames.get(node.getId().getText()) ));
390                                }
391                              }
392                            }
393                           );
394   }
395 
396   private List cloneList(List list)
397   {
398     List clone = new LinkedList();
399 
400     for(Iterator i = list.iterator(); i.hasNext();)
401     {
402       clone.add(((Node) i.next()).clone());
403     }
404 
405     return clone;
406   }
407 
408   class BooleanEx
409   {
410     boolean value;
411 
412     BooleanEx(boolean value)
413     {
414       this.value = value;
415     }
416 
417     void setValue(boolean value)
418     {
419       this.value = value;
420     }
421 
422     boolean getValue()
423     {
424       return value;
425     }
426   }
427 
428 }