A modular organization with inheritance

A meta-grammar is organized in a modular way through an hierarchy of classes. A class is a bag of constraints used to specify a syntactic phenomena (or just a facet of it) .

The classes of FRMG may be browsed here. Once a class is selected, the right side panel "Class Graph View" may be used to navigate through the class hierarchy.

The following figure shows a fragment of the FRMG hierarchy (the full hierarchy is too large and deep to fit on a page)

As an example, a very basic class for adverbs will only specify that we expect an elementary tree anchored by an adverb. No more !

class adverb {                    ...                   }

We can define subclasses that inherits all the constraints from its parent class and that may be used to progressively refine syntactic phenomena.
For instance, we may have a subclass of adverb specifying constraints about the use of adverbs as modifiers (their most common usage), essentially indicating that we expect an auxiliary tree.
We can then further refine into the notion of adverb as modifier of verbs, by specifying that the root node should have category v, with maybe some other restriction on the type of the adverb.

class adverb_as_modifier {                     <: adverb; %% this class inherits from the adverb class                     ...                  }                  class adverb_as_verb_modifier {                     <: adverb_as_modifier;                     ....                  }

Combining resources

Besides inheritance, modularity is ensured through the use of another very powerful mechanism, namely by providing/consuming resources. A class may require some resource (or functionality) that will be provided by some other class. For instance, the previous class adverb_as_modifier may be implemented by requiring the functionality of "modifier of something" through asking for resource x_modifier. The class x_modifier will be used to provide this resource. Several classes may be in competition to provide a same resource, and several classes may require a same resource.

class adverb_as_modifier {                       <: adverb;                       - x_modifier; # require the functionality "modifier_of_something"                       ....                    }                    class X_modifier {                       + x_modifier; # provide the foncionality "modifier_of_something"                       ...                    }

This resource management mechanism is quite powerful and nicely complements inheritance. In particular, it has been extended to allow a resource to be consumed several times by a class using distinct name spaces, something that can't be easily done through inheritance.

For instance, a basic resource agreement may be defined to provide agreement on gender, number, ... between a node N and its father node. This resource is consumed twice in class superlative_as_adj_mod, once in namespace det and one in namespace adj, acting on different nodes each times.

class superlative_as_adj_mod {                       <: superlative_as_mod;                       %% require agreemnt for the determiner (le|la) and the adjective                        - det::agreement; det=det::N;                       - adj::agreement; adj=adj::N;                       ...                   }                   class agreement {                       + agreement;                       %% provide agreement constraint between a node and its father                       father(N).bot.gender = node(N).bot.gender;                       ....                   }

However, historically, resources were mostly introduced for verbs to accept several verbal arguments, each one being seem as requiring a arg resource, as implement in class verb_categorization.

class verb_categorization    {       + verbalCategorization;       node(v).cat = value(v|aux);         - arg0::varg; desc.@arg0 = $arg0::arg;$arg0::arg.kind = value(-|subj|nosubj|prepobj);        - arg1::varg; desc.@arg1 = $arg1::arg; ... - arg2::varg; desc.@arg2 =$arg2::arg;       ...   }   class verb_categorization_passive    {       <: verb_categorization;       desc.ht.diathesis = value(passive);       $arg1::arg.kind = value(subj);$arg1::arg.pcas = value(-);       $arg0::arg.kind = value(-|prepobj);$arg0::arg.pcas = value(-|par|contre);       $arg2::arg.kind = value(-|prepobj|prepvcomp|prepscomp|prepacomp|acomp|scomp);$arg2::arg.pcas = value(~par);       ...   }

Inheritance and resources form the backbone of a meta-grammars (its organization in terms of class). The "flesh" is provided by the content of the classes, through constraints over the nodes of the elementary trees.

Topological constraints

First, we have topological or structural constraints:

• equality between nodes
• precedence: a node should precede another one in a tree
• dominance: a node should dominate another one in a tree. We distinguish the parent dominance (a node is a father of another one) and the ancestor dominance (a node is an ancestor of another one)

For instance, in first approximation, in a sentence, the Subject node should precede its verb node, and both nodes are dominated by the root S node. We can be more precise and state that S should be the father of the Subject.

class very_simple_intransitive_verb {                   %% declaration of nodes S, v, and Subject, with some decorations                    node S: [cat: S, type: std];                    node v: [cat: v, type: anchor, id: v];                    node Subject: [cat: N2, type: subst, id: subject];                    %% The subject precedes the verb                    Subject < v;                    %% The sentence node dominates the subject node                    S >> Subject;                    %% the sentence node also dominates the verb node, but indirectly                    %% (to allow other nodes in-between)                     S >>+ v;                    ....                 }

Decoration constraints

We have also constraints over the decorations carried by the nodes. The decoration constraints may be directly carried on nodes, or expressed as equations between feature paths and values. The source of a feature path is generally a node, but can actually be the class itself denoted by desc (equivalent to this or self in object-oriented languages) or a variable (prefixed by $as in$foo).