source: default/trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/actions/GenerateCompositeBNFAction.java @ 17

Last change on this file since 17 was 17, checked in by zeiss, 14 years ago

sdfsd

  • Property svn:mime-type set to text/plain
File size: 15.6 KB
Line 
1package de.ugoe.cs.swe.bnftools.ui.actions;
2
3import java.io.ByteArrayInputStream;
4import java.io.InputStream;
5import java.util.LinkedList;
6
7import org.eclipse.core.resources.IFile;
8import org.eclipse.core.resources.IResource;
9import org.eclipse.core.resources.ResourcesPlugin;
10import org.eclipse.core.runtime.CoreException;
11import org.eclipse.core.runtime.IPath;
12import org.eclipse.core.runtime.Path;
13import org.eclipse.emf.common.util.EList;
14import org.eclipse.emf.common.util.URI;
15import org.eclipse.emf.ecore.resource.Resource;
16import org.eclipse.jface.action.IAction;
17import org.eclipse.jface.dialogs.InputDialog;
18import org.eclipse.jface.viewers.ISelection;
19import org.eclipse.jface.viewers.IStructuredSelection;
20import org.eclipse.jface.viewers.StructuredSelection;
21import org.eclipse.jface.viewers.TreePath;
22import org.eclipse.jface.viewers.TreeSelection;
23import org.eclipse.ui.PlatformUI;
24import org.eclipse.ui.actions.ActionDelegate;
25import org.eclipse.xtext.parsetree.AbstractNode;
26import org.eclipse.xtext.parsetree.CompositeNode;
27import org.eclipse.xtext.parsetree.LeafNode;
28import org.eclipse.xtext.parsetree.NodeUtil;
29import org.eclipse.xtext.resource.XtextResource;
30import org.eclipse.xtext.resource.XtextResourceSet;
31
32import de.ugoe.cs.swe.bnftools.ebnf.ExtRule;
33import de.ugoe.cs.swe.bnftools.ebnf.GlobalCombinator;
34import de.ugoe.cs.swe.bnftools.ebnf.HookCombinator;
35import de.ugoe.cs.swe.bnftools.ebnf.Import;
36import de.ugoe.cs.swe.bnftools.ebnf.Rule;
37import de.ugoe.cs.swe.bnftools.ebnf.RuleCombinator;
38import de.ugoe.cs.swe.bnftools.ebnf.impl.EtsiBnfImpl;
39
40public class GenerateCompositeBNFAction extends ActionDelegate{
41
42        private IStructuredSelection selection = StructuredSelection.EMPTY;
43        private IFile file=null;
44        private XtextResource coreGrammar=null;
45        private LinkedList<XtextResource> packageGrammars;
46        private XtextResource xtextResource;
47        private LinkedList<URI> deltas;
48        private String global=null;
49       
50       
51        @Override
52        public void run(IAction action) {
53                TreeSelection treeSelection = (TreeSelection) selection;
54                TreePath[] paths = treeSelection.getPaths();
55
56                for (int i = 0; i < paths.length; i++) {
57                        TreePath path = paths[i];
58                        IFile f = (IFile) path.getLastSegment();
59                        XtextResourceSet set = new XtextResourceSet();
60                        String fp = f.getFullPath().toString();
61                        URI uri = URI.createPlatformResourceURI(fp,true);
62
63                        Resource resource = set.getResource(uri, true);
64                        if (resource instanceof XtextResource) {
65                                       
66                                xtextResource = (XtextResource) resource;
67                               
68                                if(!((EtsiBnfImpl) xtextResource.getParseResult().getRootNode().getElement()).getType().equals("/merge"))
69                                        continue;
70               
71                                InputDialog di = new InputDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Name Selection",
72                                                "Please type a name for the composite grammar.", uri.trimFileExtension().segment(uri.segmentCount()-1) + "_composite.bnf", null);
73                                di.open();
74                                String fname = di.getValue();
75                                                               
76                                String loc = uri.trimFileExtension().trimSegments(1).toPlatformString(true);
77
78                                String floc = loc.concat("/" + fname);
79                                IPath filePath = new Path(floc);
80                                file = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
81                                   
82                                   try {
83                                   if (!file.exists()) {
84                                      byte[] bytes = ("//Automatically generated merge grammar from: " + uri.trimFileExtension().segment(uri.segmentCount()-1) + '\n').getBytes();
85                                      InputStream source = new ByteArrayInputStream(bytes);
86                                      file.create(source, IResource.NONE, null);                                     
87                                   }
88                                   else return;
89                                        } catch (CoreException e) {
90                                                e.printStackTrace();
91                                        }
92
93                                        String coreName = null;
94                                        // get the core grammar
95                                        EList<Import> imports = ((EtsiBnfImpl) xtextResource.getParseResult().getRootNode().getElement()).getImportSection().getImports();
96                                        for(int j=0; j< imports.size(); j++) {
97                                                if(imports.get(j).getGrammarType().equals("core"))
98                                                        coreName=imports.get(j).getImportURI();
99                                        }
100                                        IPath corePath = new Path(loc.concat("/" + coreName));
101                                    IFile core = ResourcesPlugin.getWorkspace().getRoot().getFile(corePath);
102                                        createNewLine("grammar "+ "remame;" + '\n');
103                                       
104                                        String fp2 = core.getFullPath().toString();
105                                        URI coreUri = URI.createPlatformResourceURI(fp2,true);
106
107                                        Resource coreResource = set.getResource(coreUri, true);
108                                       
109                                        if(coreResource instanceof XtextResource )
110                                                coreGrammar = (XtextResource) coreResource;
111                                       
112                                        //get the package grammars
113                                        packageGrammars = new LinkedList<XtextResource>();
114                                        deltas = new LinkedList<URI>();
115                                    EList<Import> packages = ((EtsiBnfImpl) xtextResource.getParseResult().getRootNode().getElement()).getImportSection().getImports();
116                                        for(int j=0; j<packages.size(); j++) {
117                                                if(packages.get(j).getGrammarType().equals("package")) {
118                                                        String deltaName = packages.get(j).getImportURI();
119                                                        IPath deltaPath = new Path(loc.concat("/" + deltaName));
120                                                    IFile delta = ResourcesPlugin.getWorkspace().getRoot().getFile(deltaPath);
121
122                                                        String fp3 = delta.getFullPath().toString();
123                                                        URI deltaUri = URI.createPlatformResourceURI(fp3,true);
124
125                                                    Resource deltaResource = set.getResource(deltaUri, true);
126                                       
127                                                        if(deltaResource instanceof XtextResource ) {
128                                                                packageGrammars.add((XtextResource) deltaResource);
129                                                                deltas.add(deltaUri);
130                                                }
131                                                }
132                                        }
133                                       
134                                        /*
135                                         * for every rule in the core grammar, check for extensions in the merge grammar:
136                                         * if none are found, just copy the rule
137                                         * if any are found, handle them
138                                         */
139                                       
140                                        for(AbstractNode node: NodeUtil.getAllContents( coreGrammar.getParseResult().getRootNode())) {
141                                                if(node.getElement() instanceof Rule) {
142                                                        findExtensions(node);
143                                                }
144                                        }
145                                       
146                                        /*
147                                         * for every rule in each of the delta grammars, if its a regular rule, add it to the grammar
148                                         */
149                                       
150                                        for(int j=0; j<packageGrammars.size(); j++) {
151                                                createNewLine("\n");
152                                                for(AbstractNode node: NodeUtil.getAllContents(packageGrammars.get(j).getParseResult().getRootNode())){
153                                                        if(node.getElement() instanceof Rule)
154                                                                createNewLine(node.serialize().trim() + '\n');
155                                                }
156                                        }
157                        }
158                }
159               
160        }
161       
162        /*
163         * 1. go through all the rules of the merge grammar.
164         * 2. add all the rules with the same name as the given rule to a list
165         *              2.1 if none are found, copy the rule
166         *              2.2 else, copy the rule to the first extension point, then handle it and so on.
167         */
168        private void findExtensions(AbstractNode node) {
169               
170                LinkedList<AbstractNode> extensions = new LinkedList<AbstractNode>();
171                String ruleC = null;
172               
173                for(AbstractNode extension: NodeUtil.getAllContents( xtextResource.getParseResult().getRootNode())) {
174                       
175                        if(extension.getElement() instanceof GlobalCombinator)
176                                global=((GlobalCombinator) extension.getElement()).getLogic();
177                       
178                       
179                        if(extension.getElement() instanceof RuleCombinator)
180                                if(((Rule) node.getElement()).getName()
181                                                .equals(((RuleCombinator) extension.getElement()).getName()))
182                                ruleC=((RuleCombinator) extension.getElement()).getLogic();
183                       
184                       
185                        if(extension.getElement() instanceof HookCombinator){
186                                if(((Rule) node.getElement()).getName()
187                                                .equals(((HookCombinator) extension.getElement()).getName()))
188                                        extensions.add(extension);
189                        }
190                }
191               
192                if(extensions.size()==0)
193                        createNewLine(removeNewLines(node) + '\n');
194                else {
195                        createNewLine(handleExtensions(node, extensions, ruleC).trim() + '\n');
196                }
197        }
198       
199       
200        private String handleExtensions(AbstractNode node, LinkedList<AbstractNode> extensions, String ruleC) {
201               
202                int oldOffset=0;
203                int newOffset=0;
204                String fullRule = ((Rule) node.getElement()).getName().trim() + " ::= ";
205               
206                while(extensions.size()>0) {
207                       
208                        AbstractNode current = selectFirstExtension(extensions);
209                        newOffset=((HookCombinator) current.getElement()).getRuleext();
210                        fullRule=fullRule.concat(splitRule(node, oldOffset, newOffset));
211                        fullRule=fullRule.concat(resolveReferences(((HookCombinator) current.getElement()), ruleC));
212                        oldOffset=newOffset;
213                }
214                fullRule=fullRule.concat(splitRule(node, newOffset, Integer.MAX_VALUE));
215                return fullRule;
216        }
217       
218        //returns the portion of the rule between startOffset and endOffset
219        private String splitRule(AbstractNode node, int startOffset, int endOffset) {
220               
221                EList<LeafNode> leaves = node.getLeafNodes();
222                boolean rightSide=true;
223                String temp = "";
224                int waiting=0;
225               
226                for(int i=0; i<leaves.size(); i++) {
227                       
228                        if(rightSide) {
229                                if((leaves.get(i).serialize().equals("::=")) || (leaves.get(i).serialize().equals("<-")))
230                                        rightSide=false;
231                                continue;
232                        }
233                       
234                        if(startOffset==endOffset)
235                                break;
236                       
237                        if((leaves.get(i).getGrammarElement() instanceof org.eclipse.xtext.impl.TerminalRuleImpl)) {
238                                continue;
239                        }
240                       
241                        if(startOffset>waiting) {
242                                waiting++;
243                                continue;
244                        }
245                       
246                        waiting = Integer.MAX_VALUE;
247                        temp=temp.concat(leaves.get(i).serialize().trim() + " ");
248                        startOffset++;
249                }
250               
251                return temp;
252        }
253       
254
255        /*
256         * given a hook combinator, return the string of the full concatenated extensions at the point
257         */
258        private String resolveReferences(HookCombinator hookCombinator, String ruleC) {
259               
260                EList<String> labels = hookCombinator.getLABEL();
261               
262                if(labels.size()==1) {
263                        /*
264                         * take the only label and find the corresponding delta grammar
265                         * in that delta grammar, take the rule with the same name and the same extension point
266                         * and return its left side
267                         */
268                        return resolveSingleReference(labels.get(0), hookCombinator);
269                }
270               
271       
272                String combinator=null;
273               
274                if(hookCombinator.getLogic()!=null)
275                        combinator=hookCombinator.getLogic();
276               
277                else if(ruleC!=null)
278                        combinator=ruleC;
279               
280                else if(global!=null)
281                        combinator=global;
282               
283                else
284                        combinator="/and";
285                       
286               
287                if(combinator.equals("/and")) {
288                        String temp = "";
289                        for(int i=0; i<labels.size(); i++) {
290                                temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
291                        }
292                        return temp;
293                }
294               
295                if(combinator.equals("/andr")) {
296                        String temp = "";
297                        for(int i=labels.size()-1; i>-1; i--) {
298                                temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
299                        }
300                        return temp;
301                }
302               
303                if(combinator.equals("/or")) {
304                        String temp = "( ";
305                        String temp2 = null;
306                        boolean illegal=false;
307                        for(int i=0; i<labels.size()-1; i++) {
308                                temp2 = resolveSingleReference(labels.get(i), hookCombinator).trim();
309                               
310                                if ((temp2.startsWith("|"))|(temp2.startsWith(")"))|(temp2.endsWith("|"))|temp2.endsWith("(")){
311                                        illegal=true;
312                                        break;
313                                }
314                                temp=temp.concat(resolveSingleReference(labels.get(i), hookCombinator) + " | ");
315                        }
316                       
317                        temp2 = resolveSingleReference(labels.get(labels.size()-1), hookCombinator).trim();
318                       
319                        if ((temp2.startsWith("|"))|(temp2.startsWith(")"))|(temp2.endsWith("|"))|temp2.endsWith("(")){
320                                illegal=true;
321                        }
322                       
323                        temp=temp.concat(resolveSingleReference(labels.get(labels.size()-1), hookCombinator) + ") ");
324                       
325                        if(illegal) {
326                                temp="";
327                                for(int i=0; i<labels.size(); i++) {
328                                        temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
329                                }
330                        }
331                        return temp;
332                }
333               
334//              if(combinator.equals("/orr")) {
335//                      String temp = "( ";
336//                      for(int i=labels.size()-1; i>0; i--) {
337//                              temp=temp.concat(resolveSingleReference(labels.get(i), hookCombinator) + " | ");
338//                      }
339//                     
340//                      temp=temp.concat(resolveSingleReference(labels.get(0), hookCombinator) + ") ");
341//                      return temp;
342//                     
343//              }
344               
345                if(combinator.equals("/any")) {
346                        String temp2 = null;
347                        boolean illegal=false;
348                        String temp = "( ";
349                       
350                        for(int i=0; i<labels.size(); i++) {
351                                temp2 = resolveSingleReference(labels.get(i), hookCombinator).trim();
352                               
353                                if ((temp2.startsWith("|"))|(temp2.startsWith(")"))|(temp2.endsWith("|"))|temp2.endsWith("(")){
354                                        illegal=true;
355                                        break;
356                                }
357                                temp=temp.concat(resolveSingleReference(labels.get(i), hookCombinator) + " | ");
358                        }
359                       
360                        if(illegal){
361                                temp="";
362                                for(int i=0; i<labels.size(); i++) {
363                                        temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
364                                }
365                                return temp;
366                        }
367                       
368                        temp=temp.concat("( ");
369                        for(int i=0; i<labels.size(); i++) {
370                                temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
371                        }
372                        temp=temp.concat(") | ");
373                       
374                        temp=temp.concat("( ");
375                        for(int i=labels.size()-1; i>-1; i--) {
376                                temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
377                        }
378                        temp=temp.concat(")) ");
379                       
380                        return temp;
381                }
382               
383                if(combinator.equals("/together")) {
384                       
385                        String temp = "(( ";
386                       
387                        for(int i=0; i<labels.size(); i++) {
388                                temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
389                        }
390                        temp=temp.concat(") | ");
391                       
392                        temp=temp.concat("( ");
393                        for(int i=labels.size()-1; i>-1; i--) {
394                                temp=temp.concat(resolveSingleReference(labels.get(i),hookCombinator));
395                        }
396                        temp=temp.concat(")) ");
397                       
398                        return temp;
399                }
400               
401                return " \" operator other than and, andr, or, or interleave \" ";
402        }
403       
404       
405        private String resolveSingleReference(String label, HookCombinator hookCombinator) {
406               
407                URI grammarURI = deltas.get(Character.getNumericValue(label.charAt(label.length()-1))-1);
408                XtextResourceSet set = new XtextResourceSet(); 
409                Resource resource = set.getResource(grammarURI, true);
410                if (resource instanceof XtextResource) {
411                        XtextResource deltaG = (XtextResource) resource;
412                        AbstractNode rule = selectRule( hookCombinator.getName(), hookCombinator.getRuleext(), deltaG.getParseResult().getRootNode());
413                        return splitRule(rule, 0, Integer.MAX_VALUE);
414                }
415               
416                return "error - file isn't a Xtext Resource";
417        }
418        private AbstractNode selectRule(String ruleName, int extension, CompositeNode grammar) {
419                AbstractNode rule = null;
420                for(AbstractNode currentRule: NodeUtil.getAllContents(grammar)) {
421                        if( (currentRule.getElement() instanceof ExtRule)
422                                        && (((ExtRule) currentRule.getElement()).getName().equals(ruleName))
423                                        && (((ExtRule) currentRule.getElement()).getRuleext()==extension))
424                                return currentRule;
425                }
426                return rule;
427               
428        }
429        private AbstractNode selectFirstExtension(LinkedList<AbstractNode> rules) {
430               
431                AbstractNode first = rules.get(0);
432                int index = 0;
433                for(int i=0; i<rules.size(); i++) {
434                        if(((HookCombinator) first.getElement()).getRuleext() > ((HookCombinator) rules.get(i).getElement()).getRuleext()) {
435                                first=rules.get(i);
436                                index=i;
437                        }
438                }
439                rules.remove(index);
440                return first;
441               
442        }
443       
444        private String removeNewLines(AbstractNode node) {
445                EList<LeafNode> leaves = node.getLeafNodes();
446                String temp = "";
447                for(int i=0; i<leaves.size(); i++) {
448                        if(!(leaves.get(i).getGrammarElement() instanceof org.eclipse.xtext.impl.TerminalRuleImpl))
449                                temp=temp.concat(leaves.get(i).serialize() + " ");
450                }
451                return temp;
452        }
453       
454        private void createNewLine(String rule) {
455                try {
456                           if (file.exists()) {
457                              byte[] bytes = (rule).getBytes();
458                              InputStream source = new ByteArrayInputStream(bytes);
459                              file.appendContents(source, IResource.NONE, null);
460                           }
461                                } catch (CoreException e) {
462                                        e.printStackTrace();
463                        }
464        }
465        @Override
466        public void selectionChanged(IAction action, ISelection selection) {
467                if (selection instanceof IStructuredSelection) {
468                        this.selection = (IStructuredSelection) selection;
469                } else {
470                        this.selection = StructuredSelection.EMPTY;
471                }
472        }
473}
Note: See TracBrowser for help on using the repository browser.