I am trying to write a plugin to the Open Source AADL Tool Environment (OSATE) which is a plugin to Eclipse to parse an annex sublanguage. (AADL is Architecture Analysis and Design Language for embedded systems. AADL allows definition of custom annex sublanguages for which OSATE will invoke a custom parser.) OSATE itself parses AADL generating trees conforming to an Ecore/EMF metamodel defined using the Topcased graphical Ecore editor. OSATE expects custom annex sublanguage parsers to generate EMF as well.
The example AADL annex sublanguage plugin uses ANTLR (v2) to define a parser which constructs an abstract syntax tree with tree nodes generated by factories automatically generated from the Ecore metamodel: http://la.sei.cmu.edu/aadl-wiki/index.php/Sublanguage_Example
The hand-written example unparser tests EMF tree nodes using "instanceof".
I wrote a parser for my annex sublanguage using ANTLR v3 that generates ASTs of nodes that are a subclass of CommonTree, and an unparser using a tree parser that invokes string templates. My test rig reads files, parses and unparses, and writes pretty-printed files that look great.
I can't figure out how to create an Ecore metamodel that implements the Tree interface so that an ANTLR v3 tree parser can walk them. Ecore/EMF defines everything with its own E-objects (EClass, EPackage, EDataType, EString, EOperation, etc.).
ANTLR v3 tree parsers are perfect for testing whether an AST has a certain form or property, and for building a new AST while walking another one.
How can I get ANTLR v3 tree parsers to walk EMF trees?
Comments (1)
Jan 02, 2009
Brian Larson says:
The short answer is: create your own tree node that extends the EMF-generated cl...The short answer is: create your own tree node that extends the EMF-generated class, and implements org.antlr.runtime.Tree.
Use org.antlr.runtime.tree.CommonTree and org.antlr.runtime.tree.BaseTree as examples for the methods you need to make. Make your own tree adapter by extending org.antlr.runtime.tree.CommonTreeAdaptor, and your own error node by extending your tree node so it includes everything in org.antlr.runtime.tree.CommonErrorNode.
I had the usual problems getting the dependencies right. You need to get org.antlr.runtime, org.antlr.runtime.tree, and org.antlr.stringtemplate, in the Imported Packages box under the Dependencies tab of plugin.xml. You also need to put stringtemplate-3.2.jar and antlr-3.1.1-runtime.jar in the Classpath box under the Runtime tab.
Remember to Export your plugin to the folder from which you launch OSATE, quit, and restart OSATE for your changes to take effect.
I expected to throw CassCastException, but it didn't happen in my parser. Instead I had conflicts with the generated EMF classes and those in edu.cmu.sei.model.core! It was devilishly difficult to find because OSATE catches and suppresses the exception. Nothing happens with no error report to the console.
The problem is that the TOPCASED ecore diagram editor generates copies of all the classes you use from edu.cmu.sei.model.core. I was trying to return a myModel.AnnexSubclause object when edu.cmu.sei.model.core.AnnexSubclause was expected by OSATE. You must delete all the classes TOPCASED generates, and their implementations, that are contained in edu.cmu.sei.model.core, importing them explicitly whenever used by your classes.
I also had some trouble with an old ANTLR v3 plugin that generated 3.0.1 parsers. Use ANTLRWorks to explicitly generate code instead.
The Cheat Sheet called "Create AADL Annex" is helpful in addition to the sublanguage example liked above, but ignore the step implementing IAnnexFactory.
A snap of my ecore diagram of my EMF model, my tree node, my tree adaptor, and my error node are attached.
--Brian