We are familiar with the advantages of class inheritance in object-oriented languages such as C++, C#, Java, and Python. The ability to reuse functionality via inheritance allows us to express our software design optimally, without having to write redundant code.
iLangGen encourages the reuse of grammars by supporting Grammar Inheritance, where a grammar can explicitly derive from another (base) grammar. As of now, only single inheritance is supported (i.e. it is not possible derive from more than one base grammar). A derived grammar can make use of the rules (or productions) of the base grammar, and in some cases, can override base grammar productions. Let us look at the various possibilities.
Consider the following grammar:
When we run this grammar, we get the following output:
We now derive another grammar from this grammar:
As the syntax suggests, DerivedGrammar derives from BaseGrammar. What is interesting in this grammar is that it does not have definitions for the Non-terminals A, B and C. When you run this grammar, it inherits the relevant rules from its base grammar. See the output.
Let us now look at a slight variant of the BaseGrammar.
This grammar does not have a start production. Because of this, the grammar cannot be used directly. It can only be used in the context of a derived grammar. In this sense, it is like an abstract class in OO languages.
The derived grammar defines the start symbol and uses the rules of the base grammar.
Please note that in the earlier example, the base grammar was directly usable, but not in this example. In both the cases, the derived grammar makes use of the rules defined in the base grammar, exhibiting the power of inheritance. Of course, the derived grammar can define additional productions and use them if it chooses to. See this example:
Here, D is an additional rule of the derived grammar. This is the output:
The last variant of inheritance I want to discuss involves overriding productions. Just as we can declare a funtion to be virtual in C++, in iLangGen we can declare grammar productions as virtual, thus allowing a derived grammar to provide its overriding productions.
Take alook at the following grammar:
You will notice that production B has been declared virtual. It is an empty production, but in general, it could have non-empty RHS. Since this grammar has a start production, it can be run directly. This is what you get when you run the grammar:
We get output as expected. Let us now derive a grammar from this grammar and override rule B.
When you run this grammar, you get the following output:
You can see that the overridden production participates in the generated output. You can also notice that the derived class does not have a start rule. This is an interesting generation pattern where the base class decides the overall structure of the generated text and the derived class supplies appropriate components of the structure.
This brings us to the end of today’s discussion on grammar inheritance in iLangGen. As you can see, this is a very powerful feature and will come in handy when we develop large grammars.
In the next post, we shall look at Grammar Composition, yet another technique for building grammars.
Recent Comments