From 5ee1714fd23e974d1cf2511fa398b6ce310a9807 Mon Sep 17 00:00:00 2001 From: aarne Date: Fri, 21 Dec 2007 15:10:38 +0000 Subject: [PATCH] new tutorial and reference manual --- doc/10lang-small.png | Bin 0 -> 66840 bytes doc/German.png | Bin 0 -> 21000 bytes doc/Syntax.png | Bin 0 -> 14804 bytes doc/categories.png | Bin 0 -> 4241 bytes doc/food-translet.png | Bin 0 -> 22916 bytes doc/food1.png | Bin 0 -> 22805 bytes doc/food2.png | Bin 0 -> 31506 bytes doc/foodmarket.png | Bin 0 -> 2099 bytes doc/gf-refman.html | 4545 +++++++++++++++++++++++ doc/gf-tutorial.html | 7952 +++++++++++++++++++++++++++++++++++++++++ doc/mytree.png | Bin 0 -> 2230 bytes 11 files changed, 12497 insertions(+) create mode 100644 doc/10lang-small.png create mode 100644 doc/German.png create mode 100644 doc/Syntax.png create mode 100644 doc/categories.png create mode 100644 doc/food-translet.png create mode 100644 doc/food1.png create mode 100644 doc/food2.png create mode 100644 doc/foodmarket.png create mode 100644 doc/gf-refman.html create mode 100644 doc/gf-tutorial.html create mode 100644 doc/mytree.png diff --git a/doc/10lang-small.png b/doc/10lang-small.png new file mode 100644 index 0000000000000000000000000000000000000000..49a3d0a9865a140688c48d5720a230163bfabdcf GIT binary patch literal 66840 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 z.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 literal 0 HcmV?d00001 diff --git a/doc/German.png b/doc/German.png new file mode 100644 index 0000000000000000000000000000000000000000..7c6303897a4b886ce47b8ee35d40ba63b2ec041e GIT binary patch literal 21000 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 WxMd`}a~%T%1B0ilpUXO@geCxkR7a-( literal 0 HcmV?d00001 diff --git a/doc/Syntax.png b/doc/Syntax.png new file mode 100644 index 0000000000000000000000000000000000000000..1cc8161b1a5691a34795c243583d87a34eaac6a0 GIT binary patch literal 14804 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 literal 0 HcmV?d00001 diff --git a/doc/categories.png b/doc/categories.png new file mode 100644 index 0000000000000000000000000000000000000000..afc5873c5376cb405ae12b5ec267d94e01254001 GIT binary patch literal 4241 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 ZpYO`AFQ0dvV_;xl@O1TaS?83{1ORrZN~8b) literal 0 HcmV?d00001 diff --git a/doc/food-translet.png b/doc/food-translet.png new file mode 100644 index 0000000000000000000000000000000000000000..dd622a4bfaefaa61276d4c12fdd5ddd1baf466e6 GIT binary patch literal 22916 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ÛU$dBFYW(h^ojivP z3aYEEgYNphI({Z?bLa6&MN?m4c6RnNmzV7Hy!6C%iORhB^9!r0x+YJa{Lr*g`DtBB zq?_67qX`Cg^0sW*(&D$gxoYn@8*ia=JC=K1nC=|MDEs)ocv<5Am2)3_&X}a4$ibx1 z)pYY_WW~JpuU|{mW+~bDPv2qi@%V~(<1VEyRkkyhophNTe|+jxQ4ucIEw^*;+`X&F zbJ(R(IbDx0^WwdGa@CCnbLTt#&9w22GtfQFG(lmONZI5JCWnWH``#}O zTfOnaoMRW#_wC!aVe8h`pp`7Qw+Y*NooYOG^WHtTy>acURw*}mUJn;x{ag3nebLV^ zUs^VAHddR_Y3a+gQfB)8oXiW`S6~uIK3yUMe?QI`Fd}zqq-rd{FyJqd$jd!y?nqTEu z*51;|L!8e1@V}E|6AKTP#EPFy zGqzmrxt4j7O7EW&Ml*RI6M~vR_U+t|K%lPLjEnH;C`Rw^~^^j24r9q9Uk)3ayCU>aXo4u5IeC*il zcj~eK-?JDSE|+9sv^k$#oBPpIq}z4IvQEF{&HerS*HZoc8SYt&a{ObPq_XjY_hpk8 zyZ8T+?tFVMv1<&CIozov|@?T}MIvNNy`5T$X89ctNF*##v z)Q%lHB(!I&d%Y+|ufHoTNWE@Oja~oQvu8Wi^#wRsE+iZ`RDsx>t65ruQlUr z+UIh=%inAF?AhaR{p(6KH31Hm|E9+{pX`{kj3uFHez<}F$3J$9zR!=v%lzopr06;aMLI3~& literal 0 HcmV?d00001 diff --git a/doc/food1.png b/doc/food1.png new file mode 100644 index 0000000000000000000000000000000000000000..767069dabfaee3fbea6193ab77c7c79a83b02f51 GIT binary patch literal 22805 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 Mr>mdKI;Vst0OMMmq5uE@ literal 0 HcmV?d00001 diff --git a/doc/foodmarket.png b/doc/foodmarket.png new file mode 100644 index 0000000000000000000000000000000000000000..6b0e3fbd707d69866cd9370b0a6aa768ddc4ddc1 GIT binary patch literal 2099 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 XNv_lNSklhGz`)??>gTe~DWM4fRPfX& literal 0 HcmV?d00001 diff --git a/doc/gf-refman.html b/doc/gf-refman.html new file mode 100644 index 000000000..b84079ecf --- /dev/null +++ b/doc/gf-refman.html @@ -0,0 +1,4545 @@ + + + + +GF Language Reference Manual + +

GF Language Reference Manual

+ +Aarne Ranta
+
+ +

+
+

+
+ +

+
+

+

+ +

+

+This document is a reference manual to the GF programming language. +GF, Grammatical Framework, is a special-purpose programming language, +designed to support definitions of grammars. +

+

+This document is not an introduction to GF; such introduction can be +found in the GF tutorial available on line on the GF web page, +

+

+digitalgrammars.com/gf +

+

+This manual covers only the language, not the GF compiler or +interactive system. We will however make some references to different +compiler versions, if they involve changes of behaviour having to +do with the language specification. +

+

+This manual is meant to be fully compatible with GF version 3.0 +(forthcoming). Main discrepancies with version 2.8 are indicated, +as well as with the reference article on GF, +

+

+A. Ranta, "Grammatical Framework. A Type Theoretical Grammar Formalism", +The Journal of Functional Programming 14(2), 2004, pp. 145-189. +

+

+This article will referred to as "the JFP article". +

+

+As metalinguistic notation, we will use the symbols +

+
    +
  • a === b to say that a is syntactic sugar for b +
  • a ==> b to say that a is computed (or compiled) to b +
+ + +

Overview of GF

+

+GF is a typed functional language, +borrowing many of its constructs from ML and Haskell: algebraic datatypes, +higher-order functions, pattern matching. The module system bears resemblance +to ML (functors) but also to object-oriented languages (inheritance). +The type theory used in the abstract syntax part of GF is inherited from +logical frameworks, in particular ALF ("Another Logical Framework"; in a +sense, GF is Yet Another ALF). From ALF comes also the use of dependent +types, including the use of explicit type variables instead of +Hindley-Milner polymorphism. +

+

+The look and feel of GF is close to Java and +C, due to the use of curly brackets and semicolons in structuring the code; +the expression syntax, however, follows Haskell in using juxtaposition for +function application and parentheses only for grouping. +

+

+To understand the constructs of GF, and especially their limitations in comparison +to general-purpose programming languages, it is essential to keep in mind that +GF is a special-purpose and non-turing-complete language. Every GF program is +ultimately compiled to a multilingual grammar, which consists of an +abstract syntax and a set of concrete syntaxes. The abstract syntax +defines a system of syntax trees, and each concrete syntax defines a +mapping from those syntax trees to nested tuples of strings and integers. +This mapping is compositional, i.e. homomorphic, and moreover +reversible: given a nested tuple, there exists an effective way of finding +the set of syntax trees that map to this tuple. The procedure of applying the +mapping to a tree to produce a tuple is called linearization, and the +reverse search procedure is called parsing. It is ultimately the requirement +of reversibility that restricts GF to be less than turing-complete. This is +reflected in restrictions to recursion in concrete syntax. Tree formation in +abstract syntax, however, is fully recursive. +

+

+Even though run-time GF grammars manipulate just nested tuples, at compile +time these are represented by by the more fine-grained labelled records +and finite functions over algebraic datatypes. This enables the programmer +to write on a higher abstraction level, and also adds type distinctions +and hence raises the level of checking of programs. +

+ +

The module system

+ +

Top-level and supplementary module structure

+

+The big picture of GF as a programming language for multilingual grammars +explains its principal module structure. Any GF grammar must have an +abstract syntax module; it can in addition have any number of concrete +syntax modules matching that abstract syntax. Before going to details, +we give a simple example: a module defining the category A +of adjectives and one adjective-forming function, the zero-place function +Even. We give the module the name Adj. The GF code for the +module looks as follows: +

+
+    abstract Adj = {
+      cat A ;
+      fun Even : A ;
+    }
+
+

+Here are two concrete syntax modules, one intended for mapping the trees +to English, the other to Swedish. The mappling is defined by +lincat definitions assigning a linearization type to each category, +and lin definitions assigning a linearization to each function. +

+
+    concrete AdjEng of Adj = {
+      lincat A = {s : Str} ;
+      lin Even = {s = "even"} ;
+    }
+  
+    concrete AdjSwe of Adj = {
+      lincat A = {s : AForm => Str} ;
+      lin Even = {s = table {
+        ASg Utr   => "jämn" ;
+        ASg Neutr => "jämnt" ;
+        APl       => "jämna"
+        }
+      } ;
+      param AForm = ASg Gender | APl ;
+      param Gender = Utr | Neutr ;
+    }
+
+

+These examples illustrate the main ideas of multilingual grammars: +

+
    +
  • the concrete syntax must match the abstract syntax: +
      +
    • every cat is given a lincat +
    • every fun is given a lin +
    +
+ +
    +
  • the concrete syntax is internally coherent: +
      +
    • the lin rules respect the types defined by lincat rules +
    +
+ +
    +
  • concrete syntaxes are independent of each other +
      +
    • they can use different lincat and lin definitions +
    • they can define their own parameter types (param) +
    +
+ +

+The first two ideas form the core of the static checking of GF +grammars, eliminating the possibility of run-time errors in +linearization and parsing. The third idea gives GF the expressive +power needed to map abstract syntax to vastly different languages. +

+

+Abstract and concrete modules are called top-level grammar modules, +since they are the ones that remain in grammar systems at run time. +However, in order to support modular grammar engineering, GF provides +much more module structure than strictly required in top-level grammars. +

+

+Inheritance, also known as extension, means that a module can inherit the +contents of one or more other modules to which new judgements are added, +e.g. +

+
+    abstract MoreAdj = Adj ** {
+      fun Odd : A ;
+    }
+
+

+Resource modules define parameter types and operations usable +in several concrete syntaxes, +

+
+    resource MorphoFre = {
+      param Number = Sg | Pl ;
+      param Gender = Masc | Fem ;
+      oper regA : Str -> {s : Gender => Number => Str} = 
+        \fin -> {
+          s = table {
+            Masc => table {Sg => fin ; Pl => fin + "s"} ;
+            Fem  => table {Sg => fin + "e" ; Pl => fin + "es"}
+          }
+        } ;
+    }
+
+

+By opening, a module can use the contents of a resource module +without inheriting them, e.g. +

+
+    concrete AdjFre of Adj = open MorphoFre in {
+      lincat A = {s : Gender => Number => Str} ;
+      lin Even = regA "pair" ;
+    }
+
+

+Interfaces and instances separate the contents of a resource module +to type signatures and definitions, in a way analogous to abstract vs. concrete +modules, e.g. +

+
+    interface Lexicon = {
+      oper Adjective : Type ;
+      oper even_A : Adjective ;
+    }
+  
+    instance LexiconEng of Lexicon = {
+      oper Adjective = {s : Str} ;
+      oper even_A = {s = "even"} ;
+    }
+
+

+Functors i.e. parametrized modules i.e. incomplete modules, defining +a concrete syntax in terms of an interface. +

+
+    incomplete concrete AdjI of Adj = open Lexicon in {
+      lincat A = Adjective ;
+      lin Even = even_A ;
+    }
+
+

+A functor can be instantiated by providing instances of its open interfaces. +

+
+    concrete AdjEng of Adj = AdjI with (Lexicon = LexiconEng) ;
+
+

+ +

Compilation units

+

+The compilation unit of GF source code is a file that contains a module. +Judgements outside modules are supported only for backward compatibility, +as explained here. +Every source file, suffixed .gf, is compiled to a "GF object file", +suffixed .gfo (as of GF Version 3.0 and later). For runtime grammar objects +used for parsing and linearization, a set of .gfo files is linked to +a single file suffixed .gfcc. While .gf and .gfo files may contain +modules of any kinds, a .gfcc file always contains a multilingual grammar +with one abstract and a set of concrete syntaxes. +

+

+The following diagram summarizes the files involved in the compilation process. +

+module1.gf module2.gf ... modulen.gf +

+

+==> +

+

+module1.gfo module2.gfo ... modulen.gfo +

+

+==> +

+

+grammar.gfcc +

+Both .gf and .gfo files are written in the GF source language; +.gfcc files are written in a lower-level format. The process of translating +.gf to .gfo consists of name resolution, type annotation, +partial evaluation, and optimization. +There is a great advantage in the possibility to do this +separately for GF modules and saving the result in .gfo files. The partial +evaluation phase, in particular, is time and memory consuming, and GF libraries +are therefore distributed in .gfo to make their use less arduous. +

+

+In GF before version 3.0, the object files are in a format called .gfc, +and the multilingual runtime grammar is in a format called .gfcm. +

+

+The standard compiler has a built-in make facility, which finds out what +other modules are needed when compiling an explicitly given module. +This facility builds a dependency graph and decides which of the involved +modules need recompilation (from .gf to .gfo), and for which the +GF object can be used directly. +

+ +

Names

+

+Each module M defines a set of names, which are visible in M +itself, in all modules extending M (unless excluded, as explained +here), and +all modules opening M. These names can stand for abstract syntax +categories and functions, parameter types and parameter constructors, +and operations. All these names live in the same name space, which +means that a name entering a module more than once due to inheritance or +opening can lead to a conflict. It is specified +here how these +conflicts are resolved. +

+

+The names of modules live in a name space separate from the other names. +Even here, all names must be distinct in a set of files compiled to a +multilingual grammar. In particular, even files residing in different directories +must have different names, since GF has no notion of hierarchic +module names. +

+

+Lexically, names belong to the class of identifiers. An idenfifier is +a letter followed by any number of letters, digits, undercores (_) and +primes ('). Upper- and lower-case letters are treated as distinct. +Nothing dictates the choice of upper or lower-case initials, but +the standard libraries follow conventions similar to Haskell: +

+
    +
  • upper case is used for modules, abstract syntax categories and functions, + parameter types and constructors, and type synonyms +
  • lower case is used for non-type-valued operations and for variables +
+ +

+ +

+

+"Letters" as mentioned in the identifier syntax include all 7-bit ASCII +letters. Iso-latin-1 and Unicode letters are supported in varying degrees +by different tools and platforms, and are hence not recommended in identifiers. +

+ +

The structure of a module

+

+Modules of all types have the following structure: +

+moduletype name = extends opens body +
+The part of the module preceding the body is its header. The header +defines the type of the module and tells what other modules it inherits +and opens. The body consists of the judgements that introduce all the new +names defined by the module. +

+

+Any of the parts extends, opens, and body may be empty. +If they are all filled, delimiters and keywords separate the parts in the +following way: +

+moduletype name = + extends ** open opens in { body } +
+The part moduletype name looks slightly different if the +type is concrete or instance: the name intrudes between +the type keyword and the name of the module being implemented and which +really belongs to the type of the module: +
+ concrete name of abstractname +
+The only exception to the schema of functor syntax +is functor instantiations: the instantiation +list is given in a special way between extends and opens: +
+incomplete concrete name of abstractname = + extends ** functorname with instantiations ** + open opens in { body } +
+Logically, the part "functorname with instantiations" should +really be one of the extends. This is also shown by the fact that +it can have restricted inheritance (concept defined here). +

+ +

Module types, headers, and bodies

+

+The extends and opens parts of a module header are lists of +module names (with possible qualifications, as defined below here). +The first step of type checking a module consists of verifying that +these names stand for modules of approptiate module types. As a rule +of thumb, +

+
    +
  • the extends of a module must have the same moduletype +
  • the opens of a module must be of type resource +
+ +

+However, the precise rules are a little more fine-grained, because +of the presence of interfaces and their instances, and the possibility +to reuse abstract and concrete modules as resources. The following table +gives, for all module types, the possible module types of their extends +and opens, as well as the forms of judgement legal in that module type. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
module typeextendsopensbody
abstractabstract-cat, fun, def, data
concrete of abstractconcreteresource*lincat, cat, oper, param
resourceresource*resource*oper, param
interfaceresource+resource*oper, param
instance of interfaceresource*resource*oper, param
incomplete concreteconcrete+resource+lincat, cat, oper, param
+ +

+

+The table uses the following shorthands for lists of module types: +

+
    +
  • resource*: resource, instance, concrete +
  • resource+: resource*, interface, abstract +
  • concrete+: concrete, incomplete concrete +
+ +

+The legality of judgements in the body is checked before the judgements +themselves are checked. +

+

+The forms of judgement are explained here. +

+ +

Digression: the logic of module types

+

+Why are the legality conditions of opens and extends so complicated? The best way +to grasp them is probably to consider a simplified logical model of the module +system, replacing modules by types and functions. This model could actually +be developed towards treating modules in GF as first-class objects; so far, +however, this step has not been motivated by any practical needs. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
moduleobject and type
abstract A = BA = B : type
concrete C of A = BC = B : A -> S
interface I = BI = B : type
instance J of I = BJ = B : I
incomplete concrete C of A = open I in BC = B : I -> A -> S
concrete K of A = C with (I=J)K = B(J) : A -> S
resource R = BR = B : I
concrete C of A = open R in BC = B(R) : A -> S
+ +

+

+A further step of defining modules as first-class objects would use +GADTs and record types: +

+
    +
  • an abstract syntax is a Generalized Algebraic Datatype (GADT) +
  • the target type S of concrete syntax is the type of nested + tuples over strings and integers +
  • an interface is a labelled record type +
  • an instance is a record of the type defined by the interface +
  • a functor, with a module body opening an interface, is a function + on its instances +
  • the instantiation of a functor is an application of the function to + some instance +
  • a resource is a typed labelled record, putting together an interface and + an instance of it +
  • the body of a module opening a resource is as a function on the interface + implicit in the resource; this function is immediately applied to the instance + defined in the resource +
+ +

+Slightly unexpectedly, interfaces and instances are easier to understand +in this way than resources - a resource is, indeed, more complex, since +it fuses together an interface and an instance. +

+

+ +

+

+When an abstract is used as an interface and a concrete as its instance, they +are actually reinterpreted so that they match the model. Then the abstract is +no longer a GADT, but a system of abstract datatypes, with a record field +of type Type for each category, and a function among these types for each +abstract syntax function. A concrete syntax instantiates this record with +linearization types and linearizations. +

+ +

Inheritance

+

+After checking that the extends of a module are of appropriate +module types, the compiler adds the inherited judgements to the +judgements included in the body. The inherited judgements are +not copied entirely, but their names with links to the inherited module. +Conflicts may arise in this process: a name can have two definitions in the combined +pool of inherited and added judgements. Such a conflict is always an +error: GF provides no way to redefine an inherited constant. +

+

+Simple as the definition of a conflict may sound, it has to take care of the +inheritance hierarchy. A very common pattern of inheritance is the +diamond: inheritance from two modules which themselves inherit a common +base module. Assume that the base module defines a name f: +

+
+            N
+          /   \
+        M1     M2
+          \   /
+          Base {f}
+
+

+Now, N inherits f from both M1 and M2, so is there a +conflict? The answer in GF is no, because the "two" f's are in the +end the same: the one defined in Base. The situation is thus simpler +than in multiple inheritance in languages like C++, because definitions in +GF are immutable: neither M1 nor M2 can possibly have changed +the definition of f given in Base. In practice, the compiler manages +inheritance through hierarchy in a very simple way, by just always creating +a link not to the immediate parent, but the original ancestor; this ancestor +can be read from the link provided by the immediate parent. Here is how +links are created from source modules by the compiler: +

+
+    Base {f}
+    M1 {m1}   ===>  M1 {Base.f, m1}
+    M2 {m2}   ===>  M2 {Base.f, m2}
+    N  {n}    ===>  N  {Base.f, M1.m1, M2.m2, n}
+
+

+

+ +

+

+Inheritance can be restricted. This means that a module can be specified +as inheriting only explicitly listed constants, or all constants +except ones explicitly listed. The syntax uses constant names in brackets, +prefixed by a minus sign in the case of an exclusion list. In the following +configuration, N inherits a,b,c from M1, and all names but d +from M2 +

+
+    N = M1 {a,b,c}, M2-{d}
+
+

+Restrictions are performed as a part of inheritance linking, module by module: +the link is created for a constant if and only if it is both +included in the module and compatible with the restriction. Thus, +for instance, an inadvertent usage can exclude a constant from one module +but inherit it from another one. In the following +configuration, f is inherited via M1, if M1 inherits it. +

+
+    N = M1 [a,b,c], M2-[f]
+
+

+Unintended inheritance may cause problems later in compilation, in the +judgement-level dependency analysis phase. For instance, suppose a function +f has category C as its type in M, and we only include f. The +exclusion has the effect of creating an ill-formed module: +

+
+    abstract M = {cat C ; fun f : C ;}
+    M [f]   ===> {fun f : C ;}
+
+

+One might expect inheritance restriction to be transitive: if an included +constant b depends on some other constant a, then a should be +included automatically. However, this rule would leave to hard-to-detect +inheritances. And it could only be applied later in the compilation phase, +when the compiler has not only collected the names defined, but also +resolved the names used in definitions. +

+

+Yet another pitfall with restricted inheritance is that it must be stated +for each module separately. For instance, a concrete syntax of an abstract +must exclude all those names that the abstract does, and a functor instantiation +must replicate all restrictions of the functor. +

+ +

Opening

+

+Opening makes constants from other modules usable in judgements, without +inheriting them. This means that, unlike inheritance, opening is not +transitive. +

+

+ +

+

+Opening cannot be restricted as inheritance can, but it can be qualified. +This means that the names from the opened modules cannot be used as such, but +only as prefixed by a qualifier and a dot (.). The qualifier can be any +identifier, including the name of the module. Here is an example of +an opens list: +

+
+    open A, (X = XSLTS), (Y = XSLTS), B
+
+

+If A defines the constant a, it can be accessed by the names +

+
+    a  A.a
+
+

+If XSLTS defines the constant x, it can be accessed by the names +

+
+    X.x  Y.x  XSLTS.x
+
+

+Thus qualification by real module name is always possible, and one and the same +module can be qualified in different ways at the same time (the latter can +be useful if you want to be able to change the implementations of some +constants to a different resource later). Since the qualification with real +module name is always possible, it is not possible to "swap" the names of +modules locally: +

+
+    open (A=B), (B=A) -- NOT POSSIBLE!
+
+

+The list of qualifiers names and module names in a module header may +thus not contain any duplicates. +

+ +

Name resolution

+

+ +

+

+Name resolution is the compiler phase taking place after inheritance +linking. It qualifies all names occurring in the definition parts of judgements +(that is, just excluding the defined names themselves) with the names of +the modules they come from. If a name can come from different modules (that is, +not from their common ancestor), a conflict is reported; this decision is +hence not dependent on e.g. types, which are known only at a later phase. +

+

+Qualification of names is the main device for avoiding conflicts in +name resolution. No other information is used, such as priorities between +modules. However, if a name is defined in different opened modules +but never used in the module body, +a conflict does not arise: conflicts arise only +when names are used. Also in this respect, opening is thus different from +inheritance, where conflicts are checked independently of use. +

+

+As usual, inner scope has priority in name resolution. This means that +if an identifier is in scope as a bound variable, it will not be +interpreted as a constant, unless qualified by a module name +(variable bindings are explained here). +

+ +

Functor instantiations

+

+We have dealt with the principles of module headers, inheritance, and +names in a general way that applies to all module types. The exception +is functor instantiations, that have an extra part of the instantiating +equations, assigning an instance to every interface. Here is a typical +example, displaying the full generality: +

+
+    concrete FoodsEng of Foods = PhrasesEng ** 
+      FoodsI-[Pizza] with 
+        (Syntax = SyntaxEng),
+        (LexFoods = LexFoodsEng) ** 
+      open SyntaxEng, ParadigmsEng in {
+        lin Pizza = mkCN (mkA "Italian") (mkN "pie") ;
+    }
+
+

+(The example is modified from Section 5.9 in the GF Tutorial.) +

+

+The instantiation syntax is similar to qualified opens. The left-hand-side +names must be interfaces, the right-hand-side names their instances. (Recall +that abstract can be use as interface and concrete as its +instance.) Inheritance from the functor can be restricted, typically +in the purpose of defining some excluded functions in language-specific +ways in the module body. +

+ +

Completeness

+

+ +

+

+(This section refers to the forms of judgement introduced here.) +

+

+A concrete is complete with respect to an abstract, if it +contains a lincat definition for every cat declaration, and +a lin definition for every fun declaration. +

+

+The same completeness criterion applies to functor instantiations. +It is not possible to use a partial functor instantiation, leading +to another functor. +

+

+Functors do not need to be complete in the sense concrete modules need. +The missing definitions can then be provided in the body of each +functor instantiation. +

+

+A resource is complete, if all its oper and param judgements +have a definition part. While a resource must be complete, an +interface need not. For an interface, it is the definition +parts of judgements are optional. +

+

+An instance is complete with respect to an interface, if it +gives the definition parts of all oper and param judgements +that are omitted in the interface. Giving definitions to judgements +that have already been defined in the interface is illegal. +Type signatures, on the other hand, can be repeated if the same types +are used. +

+

+In addition to completing the definitions in an interface, +its instance may contain other judgements, but these must all +be complete with definitions. +

+

+Here is an example of an instance and its interface showing the +above variations: +

+
+    interface Pos = {
+      param Case ;                 -- no definition
+      param Number = Sg | Pl ;     -- definition given
+      oper Noun : Type = {         -- relative definition given
+        s : Number => Case => Str
+      } ;
+      oper regNoun : Str -> Noun ; -- no definition
+    }
+  
+    instance PosEng of Pos = {
+      param Case = Nom | Gen ;     -- definition of Case
+                                   -- Number and Noun inherited
+      oper regNoun = \dog -> {     -- type of regNoun inherited
+        s = table {                -- definition of regNoun
+          Sg => table {
+            Nom => dog
+            -- etc
+          }
+        } ;
+      oper house_N : Noun =        -- new definition
+        regNoun "house" ;
+    }
+
+

+ +

Judgements

+ +

Overview of the forms of judgement

+

+ +

+

+A module body in GF is a set of judgements. Judgements are +definitions or declarations, sometimes combinations of the two; the +common feature is that every judgement introduces a name, which is +available in the module and whenever the module is extended or opened. +

+

+There are several different forms of judgement, identified by different +judgement keywords. Here is a list of all these forms, together +with syntax descriptions and the types of modules in which each form can occur. +The table moreover indicates whether the judgement has a default value, and +whether it contributes to the name base, i.e. introduces a new +name to the scope. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
judgementwheremoduledefaultbase
cat C GG contextabstractN/Ayes
fun f : AA typeabstractN/Ayes
def f ps = tf fun, ps patterns, t termabstractyesno
data C = f | ... | gC cat, f...g funabstractyesno
lincat C = TC cat, T typeconcrete*yesyes
lin f = tf fun, t termconcrete*noyes
lindef f = tf fun, t termconcrete*yesno
printname cat C = tC cat, t termconcrete*yesno
printname fun f = tf fun, t termconcrete*yesno
param P = C| ... | DC...D constructorsresource*N/Ayes
oper f : T = tT type, t termresource*N/Ayes
flags o = vo flag, v valueallyesN/A
+ +

+

+Judgements that have default values are rarely used, except lincat and +flags, which often need values different from the defaults. +

+

+Introducing a name twice in the same module is an error. In other words, +all judgements that have a "yes" in the name base column, must +have distinct identifiers on their left-hand sides. +

+

+All judgement end with semicolons (;). +

+

+In addition to the syntax given in the table, many of the forms have +syntactic sugar. This sugar will be explained below in connection to +each form. There are moreover two kinds of syntactic sugar common to all forms: +

+
    +
  • the judgement keyword is shared between consecutive judgements + until a new keyword appears: +
    +keyw J ; K ; === keyw J ; keyw K ; +
    +
  • the right-hand sides of colon (:) and equality (=) + can be shared, by using comma (,) as separator of left-hand sides, which + must consist of identifiers +
    +c,d : T === c : T ; d : T ; +

    +c,d = t === c = t ; d = t ; +
    +
+ +

+These conventions, like all syntactic sugar, are performed at an +early compilation phase, directly after parsing. This means that e.g. +

+
+    lin f,g = \x -> x ;
+
+

+can be correct even though f and g required different +function types. +

+

+Within a module, judgements can occur in any order. In particular, +a name can be used before it is introduced. +

+

+The explanations of judgement forms refer to the notions +of type and term (the latter also called expression). +These notions will be explained in detail here. +

+ +

Category declarations, cat

+

+ +

+

+Category declarations +

+cat C G +
+define the basic types of abstract syntax. +A basic type is formed from a category by giving values to all variables +in the context G. If the context is empty, the +basic type looks the same as the category itself. Otherwise, application +syntax is used: +
+C a1...an +
+

+ +

Hypotheses and contexts

+

+ +

+

+A context is a sequence of hypotheses, i.e. variable-type pairs. +A hypothesis is written +

+( x : T ) +
+and a sequence does not have any separator symbols. As syntactic sugar, +

+
    +
  • variables can share a type, +
    +( x,y : T ) === ( x : T ) ( y : T ) +
    +
  • a wildcard can be used for a variable not occurring in types + later in the context, +
    +( _ : T ) === ( x : T ) +
    +
  • if the variable does not occur later, it can be omitted altogether, and + parentheses are not used, +
    + T === ( x : T ) +
    + But if T is more complex than an identifier, it needs parentheses to + be separated from the rest of the context. +
+ +

+An abstract syntax has dependent types, if any of its categories has +a non-empty context. +

+ +

Function declarations, fun

+

+Function declarations, +

+ fun f : T +
+define the syntactic constructors of abstract +syntax. The type T of f +is built built from basic types (formed from categories) by using +the function type constructor ->. Thus its form is +
+ (x1 : A1) -> ... -> (xn : An) -> B +
+where Ai are types, called the argument types, and B is a +basic type, called the value type of f. The value category of +f is the category that forms the type B. +

+

+A syntax tree is formed from f by applying it to a full list of +arguments, so that the result is of a basic type. +

+

+A higher-order function is one that has a function type as an +argument. The concrete syntax of GF does not support displaying the +bound variables of functions of higher than second order, but they are +legal in abstract syntax. +

+

+An abstract syntax is context-free, if it has neither dependent +types nor higher-order functions. Grammars with context-free abstract +syntax are an important subclass of GF, with more limited complexity +than full GF. Whether the concrete syntax is context-free in the sense +of the Chomsky hierarchy is independent of the context-freeness of +the abstract syntax. +

+ +

Function definitions, def

+

+Function definitions, +

+ def f p1 ... pn = t +
+where f is a fun function and pi# are patterns, +impose a relation of definitional equality on abstract syntax +trees. They form the basis of computation, which is used +when comparing whether two types are equal; this notion is relevant +only if the types are dependent. Computation can also be used for +the normalization of syntax trees, which applies even in +context-free abstract syntax. +

+

+The set of def definitions for f can be scattered around +the module in which f is introduced as a function. The compiler +builds the set of pattern equations in the order in which the +equations appear; this order is significant in the case of +overlapping patterns. All equations must appear in the same module in +which f itself declared. +

+

+The syntax of patterns will be specified here, commonly for +abstract and concrete syntax. In abstract +syntax, constructor patterns are those of the form +

+ C p1 ... pn +
+where C is declared as data for some abstract syntax category +(see next section). A variable pattern is either an identifier or +a wildcard. +

+

+A common pitfall is to forget to declare a constructor as data, which +causes it to be interpreted as a variable pattern in definitions. +

+

+Computation is performed by applying definitions and beta conversions, +and in general by using pattern matching. Computation and pattern matching +are explained commonly for abstract and concrete syntax here. +

+

+In contrast to concrete syntax, abstract syntax computation is +completely symbolic: it does not produce a value, but just another +term. Hence it is not an error to have incomplete systems of +pattern equations for a function. In addition, the definitions +can be recursive, which means that computation can fail to terminate; +this can never happen in concrete syntax. +

+ +

Data constructor definitions, data

+

+A data constructor definition, +

+ data C = f1 | ... | fn +
+defines the functions f1...fn to be constructors +of the category C. This means that they are recognized as constructor +patterns when used in function definitions. +

+

+In order for the data constructor definition to be correct, +f1...fn must be functions with C as their value category. +

+

+The complete set of constructors for a category C is the union of +all its data constructor definitions. Thus a category can be "extended" +by new constructors afterwards. However, all these constructor definitions +must appear in the same module in which the category is itself defined. +

+

+There is syntactic sugar for declaring a function as a constructor at +the same time as introducing it: +

+data f : A1 -> ... -> An -> C t1 ... tm +

+

+ === +

+

+fun f : A1 -> ... -> An -> C t1 ... tm ; + data C = f +

+

+ +

The semantic status of an abstract syntax function

+

+There are three possible statuses for a function declared in a fun judgement: +

+
    +
  • primitive notion: the default status +
  • constructor: the function appears on the right-hand side in data judgement +
  • defined: the function has a def definition +
+ +

+The "constructor" and "defined" statuses are in contradiction with each other, +whereas the primitive notion status is overridden by any of the two others. +

+

+This distinction is relevant for the semantics of abstract syntax, not +for concrete syntax. It shows in the way patterns are treated in +equations in def definitions: a constructor +in a pattern matches only itself, whereas +any other name is treated as a variable pattern, which matches +anything. +

+ +

Linearization type definitions, lincat

+

+A linearization type definition, +

+ lincat C = T +
+defines the type of linearizations of trees whose type has category C. +Type dependences have no effect on the linearization type. +

+

+The type T must be a legal linearization type, which means that it +is a record type whose fields have either parameter types, the type Str +of strings, or table or record types of these. In particular, function types +may not appear in T. A detailed explanation of types in concrete syntax +will be given here. +

+

+If K is the concrete syntax of an abstract syntax A, then K must +define the linearization type of all categories declared in A. However, +the definition can be omitted from the source code, in which case the default +type {s : Str} is used. +

+ +

Linearization definitions, lin

+

+A linearization definition, +

+ lin f = t +
+defines the linearizations function of function f, i.e. the function +used for linearizing trees formed by f. +

+

+The type of t must be the homomorphic image of the type of f. +In other words, if +

+ fun f : A1 -> ... -> An -> A +
+then +
+ lin f : A1* -> ... -> An* -> A* +
+where the type T* is defined as follows depending on T: +

+
    +
  • (C t1 ... tn)* = T, if lincat C = T +
  • (B1 -> ... -> Bm -> B)* = B* ** {$0,...,$m : Str} +
+ +

+The second case is relevant for higher-order functions only. It says that +the linearization type of the value type is extended by adding a string field +for each argument types; these fields store the variable symbol used for +the binding of each variable. +

+

+ +

+

+Since the arguments of a function argument are treated as bare strings, +orders higher than the second are irrelevant for concrete syntax. +

+

+There is syntactic sugar for binding the variables of the linearization +of a function on the left-hand side: +

+ lin f p = t === lin f = \p -> t +
+The pattern p must be either a variable or a wildcard (_); this is +what the syntax of lambda abstracts (\p -> t) requires. +

+ +

Linearization default definitions, lindef

+

+ +

+

+A linearization default definition, +

+ lindef C = t +
+defines the default linearization of category C, i.e. the function +applicable to a string to make it into an object of the linearization +type of C. +

+

+Linearization defaults are invoked when linearizing variable bindings +in higher-order abstract syntax. A variable symbol is then presented +as a string, which must be converted to correct type in order for +linearization not to fail with an error. +

+

+The defaults can also be used for linearizing metavariables +in an interactive syntax editor. +

+

+Usually, linearization defaults are generated by using the default +rule that "uses the symbol itself for every string, and the +first value of the parameter type for every parameter". The precise +definition is by structural recursion on the type: +

+
    +
  • default(Str,s) = s +
  • default(P,s) = #1(P) +
  • default(P => T,s) = \\_ => default(T,s) +
  • default({... ; r : R ; ...},s) = {... ; r : default(R,s) ; ...} +
+ +

+The notion of the first value of a parameter type (#1(P)) is defined +here below. +

+ +

Printname definitions, printname cat and printname fun

+

+A category printname definition, +

+ printname cat C = s +
+defines the printname of category C, i.e. the name used +in some abstract syntax information shown to the user. +

+

+Likewise, a function printname definition, +

+ printname fun f = s +
+defines the printname of function f, i.e. the name used +in some abstract syntax information shown to the user. +

+

+The most common use of printnames is in the interactive syntax +editor, where printnames are displayed in menus. It is possible +e.g. to adapt them to each language, or to embed HTML tooltips +in them (as is used in some HTML-based editor GUIs). +

+

+Usually, printnames are generated automatically from the symbol +and/or concrete syntax information. +

+ +

Parameter type definitions, param

+

+ +

+

+A parameter type definition, +

+ param P = C1 G1 | ... | Cn Gn +
+defines a parameter type P with the parameter constructors +C1...Cn, with their respective contexts G1...Gn. +

+

+ +

+

+Contexts have the same syntax as in cat judgements, explained +here. Since dependent types are not available in +parameter type definitions, the use of variables is never +necessary. The types in the context must themselves be parameter types, +which are defined as follows: +

+
    +
  • Given the judgement param P ..., P is a parameter type. +
  • A record type of parameter types is a parameter type. +
  • Ints n (an initial segment of integers) is a parameter type. +
+ +

+The names defined by a parameter type definition include both the +type name P and the constructor names Ci. Therefore all these +names must be distinct in a module. +

+

+A parameter type may not be recursive, i.e. P itself may not occur in +the contexts of its constructors. This restriction extends to mutual +recursion: we say that P depends on the types that occur +in the contexts of its constructors and on all types that those types +depend on, and state that P may not depend on itself. +

+

+In an interface module, it is possible to declare a parameter type +without defining it, +

+ param P ; +
+

+ +

Parameter values

+

+ +

+

+All parameter types are finite, and the GF compiler will internally +compute them to lists of parameter values. These lists are formed by +traversing the param definitions, usually respecting the +order of constructors in the source code. For records, bibliographical +sorting is applied. However, both the order of traversal of param +definitions and the order of fields in a record are specified +in a compiler-internal way, which means that the programmer should not +rely on any particular order. +

+

+The order of the list of parameter values can affect the program in two +cases: +

+
    +
  • in the default lindef definition (here), + the first value is chosen +
  • in course-of-value tables (here), the compiler-internal order is + followed +
+ +

+The first usage implies that, if lindef definitions are essential for +the application, they should be given manually. The second usage implies that +course-of-value tables should be avoided in hand-written GF code. +

+

+In run-time grammar generation, all parameter values are translated to +integers denotions positions in these parameter lists. +

+ +

Operation definitions, oper

+

+An operation definition, +

+ oper h : T = t +
+defines an operation h of type T, with the computation rule +
+ h ==> t +
+The type T can be any concrete syntax type, including function +types of any order. The term t must have the type T, as +defined here. +

+

+As syntactic sugar, the type can be omitted, +

+ oper h = t +
+which works in two cases +

+
    +
  • the type can be inferred from t (compiler-dependent) +
  • the definition occurs in an instance and the type is given in + the interface +
+ +

+It is also possible to give the type and the definition separately: +

+oper h : T ; oper h = t === + oper h : T = t +
+The order of the type part and the definition part is free, and there +can be other judgements in between. However, they must occur in the +same resource module for it to be complete (as defined here). +In an interface module, it is enough to give the type. +

+

+When only the definition is given, it is possible to use a shorthand +similar to lin judgements: +

+oper h p = t === oper h = \p -> t +
+The pattern p is either a variable or a wildcard (_). +

+

+Operation definitions may not be recursive, not even mutually recursive. +This condition ensures that functions can in the end be eliminated from +concrete syntax code (as explained here). +

+ +

Operation overloading

+

+ +

+

+One and the same operation name h can be used for different operations, +which have to have different types. For each call of h, the type checker +selects one of these operations depending on what type is expected in the +context of the call. The syntax of overloaded operation definitions is +

+oper h + = overload {h : T1 = t1 ; ... ; h : Tn = tn} +
+Notice that h must be the same in all cases. +This format can be used to give the complete implementation; to give just +the types, e.g. in an interface, one can use the form +
+oper h + : overload {h : T1 ; ... ; h : Tn} +
+The implementation of this operation typing is given by a judgement of +the first form. The order of branches need not be the same. +

+ +

Flag definitions, flags

+

+A flag definition, +

+ flags o = v +
+sets the value of the flag o, to be used when compiling or using +the module. +

+

+The flag o is an identifier, and the value v is either an identifier +or a quoted string. +

+

+Flags are a kind of metadata, which do not strictly belong to the GF +language. For instance, compilers do not necessarily check the +consistency of flags, or the meaningfulness of their values. +The inheritance of flags is not well-defined; the only certain rule +is that flags set in the module body override the settings from +inherited modules. +

+

+Here are some flags commonly included in grammars. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
flagvaluedescriptionmodule
codingcharacter encodingencoding used in string literalsconcrete
lexerpredefined lexerlexer before parsingconcrete
startcatcategorydefault target of parsingabstract
unlexerpredefined unlexerunlexer after linearizationconcrete
+ +

+

+The possible values of these flags are specified here. +

+ +

Types and expressions

+ +

Overview of expression forms

+

+ +

+

+Like many dependently typed languages, GF makes no syntactic distinction +between expressions and types. An illegal use of a type as an expression or +vice versa comes out as a type error. Whether a variable, for instance, +stands for a type or an expression value, can only be resolved from its +context of use. +

+

+One practical consequence of the common syntax is that global and local definitions +(oper judgements and let expressions, respectively) work in the same way +for types and expressions. Thus it is possible to abbreviate a type +occurring in a type expression: +

+
+    let A = {s : Str ; b : Bool} in A -> A -> A
+
+

+Type and other expressions have a system of precedences. The following table +summarizes all expression forms, from the highest to the lowest precedence. +Some expressions are moreover left- or right-associative. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
precexpression exampleexplanation
7cconstant or variable
7Typethe type of types
7PTypethe type of parameter types
7Strthe type of strings/token lists
7"foo"string literal
7123integer literal
70.123floating point literal
7?metavariable
7[]empty token list
7[C a b]list category
7["foo bar"]token list
7{"s : Str ; n : Num}record type
7{"s = "foo" ; n = Sg}record
7<Sg,Fem,Gen>tuple
7<n : Num>type-annotated expression
6 leftt.rprojection or qualification
5 leftf afunction application
5table {Sg => [] ; _ => "xs"}table
5table P [a ; b ; c]course-of-values table
5case n of {Sg => [] ; _ => "xs"}case expression
5variants {"color" ; "colour"}free variation
5pre {"a" ; "an"/vowel}prefix-dependent choice
4 leftt ! vtable selection
4 leftA * Btuple type
4 leftR ** {b : Bool}record (type) extension
3 leftt + stoken gluing
2 leftt ++ stoken list concatenation
1 right\x,y -> tfunction abstraction ("lambda")
1 right\\x,y => ttable abstraction
1 right(x : A) -> Bdependent function type
1 rightA -> Bfunction type
1 rightP => Ttable type
1 rightlet x = v in tlocal definition
1t where {x = v}local definition
1in M.C "foo"rule by example
+ +

+

+Any expression in parentheses ((exp)) is in the highest +precedence class. +

+ +

The functional fragment: expressions in abstract syntax

+

+ +

+

+The expression syntax is the same in abstract and concrete syntax, although +only a part of the syntax is actually usable in well-typed expressions in +abstract syntax. An abstract syntax is essentially used for defining a set +of types and a set of functions between those types. Therefore it needs +essentially the functional fragment +of the syntax. This fragment comprises two kinds of types: +

+
    +
  • basic types, of form C a1...an where +
      +
    • cat C (x1 : A1)...(xn : An), including the predefined + categories Int, Float, and String explained here +
    • a1 : A1,...,an : An{x1 = a1,...,xn-1=an-1} +
    +
+ +
    +
  • function types, of form (x : A) -> B, where +
      +
    • A is a type +
    • B is a type possibly depending on x : A +
    +
+ +

+When defining basic types, we used the notation +t{x1 = t1,...,xn=tn} +for the substitution of values to variables. This is a metalevel notation, +which denotes a term that is formed by replacing the free occurrences of +each variable xi by ti. +

+

+These types have six kinds of expressions: +

+
    +
  • constants, f : A where +
      +
    • fun f : A +
    +
+ +
    +
  • literals for integers, floats, and strings (defined in here) +
+ +
    +
  • variables, x : A where +
      +
    • x has been introduced by a binding +
    +
+ +
    +
  • applications, f a : B{x=a}, where +
      +
    • f : (x : A) -> B +
    • a : A +
    +
+ +
    +
  • abstractions, \x -> b : (x : A) -> B, where +
      +
    • b : B possibly depending on x : A +
    +
+ +
    +
  • metavariables, ?, as introduced in intermediate phases of + incremental type checking; metavariables are not permitted + in GF source code +
+ +

+ +

+

+The notion of binding is defined for occurrences of variables in +subexpressions as follows: +

+
    +
  • in (x : A) -> B, x is bound in B +
  • in \x -> b, x is bound in b +
  • in def f p1 ... pn = t, any pattern variable introduced in + any pi is bound in t (as defined here) +
+ +

+As syntactic sugar, function types have sharing of types and +suppression of variables, in the same way as contexts +(defined here): +

+
    +
  • variables can share a type, +
    +( x,y : A ) -> B === + ( x : A ) -> ( y : A ) -> B +
    +
  • a wildcard can be used for a variable not occurring later in the type, +
    +( _ : A ) -> B === + ( x : T ) -> B +
    +
  • if the variable does not occur later, it can be omitted altogether, and + parentheses are not used, +
    + A -> B === ( _ : A ) -> B +
    +
+ +

+There is analogous syntactic sugar for constant functions, +

+\_ -> t === \x -> t +
+where x does not occur in t, and for multiple lambda abstractions: +
+\p,q -> t === \p -> \q -> t +
+where p and q are variables or wild cards (_). +

+ +

Conversions

+

+ +

+

+Among expressions, there is a relation of definitional equality defined +by four conversion rules: +

+
    +
  • alpha conversion: + \x -> b = \y -> b{x=y} +
+ +
    +
  • beta conversion: (\x -> b) a = b{x=a} +
+ +
    +
  • delta conversion: f a1 ... an = tg, if +
      +
    • there is a definition def f p1 ... pn = t +
    • this definition is the first for f that matches the sequence + a1 .... an, with the substitution g +
    +
+ +
    +
  • eta conversion: c = \x -> c x, + if c : (x : A) -> B +
+ +

+Pattern matching substitution used in delta conversion +is defined here. +

+

+An expression is in beta-eta-normal form if +

+
    +
  • it has no subexpressions to which beta conversion applies (beta normality) +
  • each constant or variable whose type is a function type must be + eta-expanded, i.e. made into an abstract equal to it by eta conversion + (eta normality) +
+ +

+Notice that the iteration of eta expansion would lead to an expression not +in beta-normal form. +

+ +

Syntax trees

+

+ +

+

+The syntax trees defined by an abstract syntax are well-typed +expressions of basic types in beta-eta normal form. +Linearization defined in concrete +syntax applies to all and only these expressions. +

+

+There is also a direct definition of syntax trees, which does not +refer to beta and eta conversions: keeping in mind that a type always has +the form +

+(x1 : A1) -> ... -> (xn : An) -> B +
+where Ai are types and B is a basic type, a syntax tree is an expression +
+b t1 ... tn : B' +
+where +

+
    +
  • B' is the basic type B{x1 = t1,...,xn = tn} +
  • fun b : (x1 : A1) -> ... -> (xn : An) -> B +
  • each ti has the form \z1,...,zm -> c where Ai is +
    +(y1 : B1) -> ... -> (ym : Bm) -> B +
    +
+ + +

Predefined types in abstract syntax

+

+ +

+

+GF provides three predefined categories for abstract syntax, with predefined +expressions: +

+ + + + + + + + + + + + + + + + + +
categoryexpressions
Intinteger literals, e.g. 123
Floatfloating point literals, e.g. 12.34
Stringstring literals, e.g. "foo"
+ +

+

+These categories take no arguments, and they can be used as basic +types in the same way as if they were introduced in cat judgements. +However, it is not legal to define fun functions that have any +of these types as value type: their only well-typed expressions are +literals as defined in the above table. +

+ +

Overview of expressions in concrete syntax

+

+ +

+

+Concrete syntax is about defining mappings from abstract syntax trees +to concrete syntax objects. These objects comprise +

+
    +
  • records +
  • tables +
  • strings +
  • parameter values +
+ +

+Thus functions are not concrete syntax objects; however, the +mappings themselves are expressed as functions, and the source code +of a concrete syntax can use functions under the condition that +they can be eliminated from the final compiled grammar (which they +can; this is one of the fundamental properties of compilation, as +explained in more detail in the JFP article). +

+

+Concrete syntax thus has the same function types and expression forms as +abstract syntax, specified here. The basic types defined +by categories (cat judgements) are available via grammar reuse +explained here; this also comprises the +predefined categories Float and String. +

+ +

Values, canonical forms, and run-time variables

+

+In abstract syntax, the conversion rules fiven here +define a computational relation +among expressions, but there is no separate notion of a value of +computation: the value (the end point) of a computation chain is +simply an expression to which no more conversions apply. In general, +we are interested in expressions that satisfy the conditions of being +syntax trees (as defined here), but there can be many computationally +equivalent syntax trees which nonetheless are distinct syntax trees +and hence have different linearizations. The main use of computation +in abstract syntax is to compare types in dependent type checking. +

+

+In concrete syntax, the notion of values is central. At run time, +we want to compute the values of linearizations; at compile time, we want +to perform partial evaluation, which computes expressions as far as +possible. +To specify what happens +in computation we therefore have to distinguish between canonical forms +and other forms of expressions. The canonical forms are defined separately +for each form of type, whereas the other forms may usually produce expressions +of any type. +

+

+ + +

+

+What is done at compile time is the elimination of any noncanonical forms, +except for those depending on run-time variables. Run-time variables are +the same as the argument variables of linearization rules, i.e. the +variables x1,...,xn in +

+lin f = \ x1,...,xn -> t +
+where +
+fun f : +(x1 : A1) -> ... -> (xn : An) -> B +
+Notice that this definition refers to the eta-expanded linearization term, +which has one abstracted variable for each argument type of f. These variables +are not necessarily explicit in GF source code, but introduced by the compiler. +

+

+Since certain expression forms should be eliminated in compilation but +cannot be eliminated if run-time variables appear in them, errors can +appear late in compilation. This is an issue with the following +expression forms: +

+
    +
  • gluing (s + t), defined here +
  • pattern matching on strings, defined here +
  • predefined string operations, defined here (those taking + Str arguments) +
+ + +

Token lists, tokens, and strings

+

+ +

+

+The most prominent basic type is Str, the type of token lists. +This type is often sloppily referred to as the type of strings; +but it should be kept in mind that the objects of Str are +lists of strings rather than single strings. +

+

+Expressions of type Str have the following canonical forms: +

+
    +
  • tokens, i.e. string literals, in double quotes, e.g. "foo" +
  • the empty token list, [] +
  • concatenation, s ++ t, where s,t : Str +
  • prefix-dependent choice, + pre { s ; s1 / p1 ; ... ; sn / pn}, where +
      +
    • s, s1,...,sn, p1,...,pn : Str +
    +
+ +

+For convenience, the notation is overloaded so that tokens are identified +with singleton token lists, and there is no separate type of tokens +(this is a change from the JFP article). +The notion of a token +is still important for compilation: all tokens introduced by +the grammar must be known at compile time. This, in turn, is +required by the parsing algorithms used for parsing with GF grammars. +

+

+In addition to string literals, tokens can be formed by a specific +non-canonical operator: +

+
    +
  • gluing, s + t, where s,t : Str +
+ +

+ +

+

+Being noncanonical, gluing is equipped with a computation rule: +string literals are glued by forming a new string literal, and +empty token lists can be ignored: +

+
    +
  • "foo" + "bar" ==> "foobar" +
  • t + [] ==> t +
  • [] + t ==> t +
+ +

+Since tokens must be known at compile time, +the operands of gluing may not depend on run-time variables, +as defined here. +

+

+As syntactic sugar, token lists can be given as bracketed string literals, where +spaces separate tokens: +

+
    +
  • token lists, ["one two three"] === "one" ++ "two" ++ "three" +
+ +

+Notice that there are no empty tokens, but the expression [] +can be used in a context requiring a token, in particular in gluing expression +below. Since [] denotes an empty token list, the following computation laws +are valid: +

+
    +
  • t ++ [] ==> t +
  • [] ++ t ==> t +
+ +

+Moreover, concatenation and gluing are associative: +

+
    +
  • s + (t + u) ==> s + t + u +
  • s ++ (t ++ u) ==> s ++ t ++ u +
+ +

+For the programmer, associativity and the empty token laws mean +that the compiler can use them to simplify string expressions. +It also means that these laws are respected in pattern matching +on strings. +

+

+A prime example of prefix-dependent choice operation is the following +approximative expression for the English indefinite article: +

+
+    pre {"a" ; "an" / variants {"a" ; "e" ; "i" ; "o"}}
+
+

+This expression can be computed in the context of a subsequent token: +

+
    +
  • pre { s ; s1 / p1 ; ... ; sn / pn} ++ t + ==> +
      +
    • si for the first i such that the prefix pi + matches t, if it exists +
    • s otherwise +
    +
+ +

+The matching prefix is defined by comparing the string with the prefix of +the token. If the prefix is a variant list of strings, then it matches +the token if any of the strings in the list matches it. +

+

+The computation rule can sometimes be applied at compile time, but it general, +prefix-dependent choices need to be passed to the run-time grammar, because +they are not given a subsequent token to compare with, or because the +subsequent token depends on a run-time variable. +

+

+The prefix-dependent choice expression itself may not depend on run-time +variables. +

+

+In GF prior to 3.0, a specific type Strs +is used for defining prefixes, +instead of just variants of Str. +

+ +

Records and record types

+

+A record is a collection of objects of possibly different types, +accessible by projections from the record with labels pointing +to these objects. A record is also itself an object, whose type is +a record type. Record types have the form +

+ { r1 : A1 ; ... ; rn : An } +
+where n >= 0, each Ai is a type, and the labels ri are +distinct. A record of this type has the form +
+ { r1 = a1 ; ... ; rn = an } +
+where each #aii : "Aii. A limiting case is the empty record type +{}, which has the object {}, the empty record. +

+

+The fields of a record type are its parts of the form r : A, +also called typings. The fields of a record are of the form +r = a, also called value assignments. Value assignments +may optionally indicate the type, as in r : A = a. +

+

+The order of fields in record types and records is insignificant: two record +types (or records) are equal if they have the same fields, in any order, and a +record is an object of a record type, if it has type-correct value assignments +for all fields of the record type. +The latter definition implies the even stronger +principle of record subtyping: a record can have any type that has some +subset of its fields. This principle is explained further +here. +

+

+All fields in a record must have distinct labels. Thus it is not possible +e.g. to "redefine" a field "later" in a record. +

+

+Lexically, labels are identifiers (defined here). +This is with the exception +of the labels selecting bound variables in the linearization of higher-order +abstract syntax, which have the form $i for an integer i, +as specified here. +In source code, these labels should not appear in records fields, +but only in selections. +

+

+Labels occur only in syntactic positions where they cannot be confused with +constants or variables. Therefore it is safe to write, as in Prelude, +

+
+    ss : Str -> {s : Str} = \s -> {s = s} ;
+
+

+A projection is an expression of the form +

+ t.r +
+where t must be a record and r must be a label defined in it. +The type of the projection is the type of that field. +The computation rule for projection returns the value assigned to that field: +
+{ ... ; r = a ; ... }.r ==> a +
+Notice that the dot notation t.r is also used for qualified names +as specified here. +This ambiguity follows tradition and convenience. It is +resolved by the following rules (before type checking): +

+
    +
  1. if t is a bound variable or a constant in scope, + t.r is type-checked as a projection +
  2. otherwise, t.r is type-checked as a qualified name +
+ +

+As syntactic sugar, types and values can be shared: +

+
    +
  • { ... ; r,s : A ; ... } === + { ... ; r : A ; s : A ; ... } +
  • { ... ; r,s = a ; ... } === + { ... ; r = a ; s = a ; ... } +
+ +

+Another syntactic sugar are tuple types and tuples, which are translated +by endowing their unlabelled fields by the labels p1, p2,... in the +order of appearance of the fields: +

+
    +
  • A1 * ... * An === + { p1 : A1 ; ... ; pn : An } +
  • <a1 , ... , an > === + { p1 = a1; ... ; pn = an } +
+ +

+A record extension is formed by adding fields to a record or a record type. +The general syntax involves two expressions, +

+ R ** S +
+The result is a record type or a record with a union of the fields of R and +S. It is therefore well-formed if +

+
    +
  • both R and S are either records or record types +
  • the labels in R and S are distinct +
+ + +

Subtyping

+

+ +

+

+The possibility of having superfluous fields in a record forms the basis of +the subtyping relation. +That A is a subtype of B means that a : A implies a : B. +This is clearly satisfied for records with superfluous fields: +

+
    +
  • if R is a record type without the label r, + then R ** { r : A } is a subtype of R +
+ +

+The GF grammar compiler extends subtyping to function types by covariance +and contravariance: +

+
    +
  • covariance: if A is a subtype of B, + then C -> A is a subtype of C -> B +
  • contravariance: if A is a subtype of B, + then B -> C is a subtype of A -> C +
+ +

+The logic of these rules is natural: if a function is returns a value +in a subtype, then this value is a fortiori in the supertype. +If a function is defined for some type, then it is a fortiori defined +for any subtype. +

+

+In addition to the well-known principles of record subtyping and co- and +contravariance, GF implements subtyping for initial segments of integers: +

+
    +
  • if m < n, then Ints m is a subtype of Ints n +
  • Ints n is a subtype of Integer +
+ +

+As the last rule, subtyping is transitive: +

+
    +
  • if A is a subtype of B and B is a subtype of C, then + A is a subtype of C. +
+ + +

Tables and table types

+

+ +

+

+One of the most characteristic constructs of GF is tables, also called +finite functions. That these functions are finite means that it +is possible to finitely enumerate all argument-value pairs; this, in +turn, is possible because the argument types are finite. +

+

+A table type has the form +

+P => T +
+where P must be a parameter type in the sense defined here, whereas +T can be any type. +

+

+Canonical expressions of table types are tables, of the form +

+table { V1 => t1 ; ... ; Vn => tn } +
+where V1,...,Vn is the complete list of the parameter values of +the argument type P (defined here), and each ti is +an expression of the value type T. +

+

+In addition to explicit enumerations, +tables can be given by pattern matching, +

+table {p1 => t1 ; ... ; pm => tm} +
+where p1,....,pm is a list of patterns that covers all values of type P. +Each pattern pi may bind some variables, on which the expression ti +may depend. A complete account of patterns and pattern matching is given +here. +

+

+A course-of-values table omits the patterns and just lists all +values. It uses the enumeration of all values of the argument type P +to pair the values with arguments: +

+table P [t1 ; ... ; tn] +
+This format is not recommended for GF source code, since the +ordering of parameter values is not specified and therefore a +compiler-internal decision. +

+

+The argument type can be indicated in ordinary tables as well, which is +sometimes helpful for type inference: +

+table P { ... } +
+

+

+The selection operator !, applied to a table t and to an expression +v of its argument type +

+t ! v +
+returns the first pattern matching result from t with v, as defined +here. The order of patterns is thus significant as long as the +patterns contain variables or wildcards. When the compiler reorders the +patterns following the enumeration of all values of the argument type, +this order no longer matters, because no overlap remains between patterns. +

+

+The GF compiler performs table expansion, i.e. an analogue of +eta expansion defined here, where a table is applied to all +values to its argument type: +

+t : P => T ==> +table P [t ! V1 ; ... ; t ! Vn] +
+As syntactic sugar, one-branch tables can be written in a way similar to +lambda abstractions: +
+\\p => t === table {p => t } +
+where p is either a variable or a wildcard (_). Multiple bindings +can be abbreviated: +
+\\p,q => t === \\p => \\q => t +
+Case expressions are syntactic sugar for selections: +
+case e of {...} === table {...} ! e +
+

+ +

Pattern matching

+

+ +

+

+We will list all forms of patterns that can be used in table branches. +We define their variable bindings and matching substitutions. +

+

+We start with the patterns available for all parameter types, as well +as for the types Integer and Str. +

+
    +
  • A constructor pattern C p1...pn + binds the union of all variables bound in the subpatterns + p1,...,pn. + It matches any value + C V1...Vn where each pi# matches Vi, + and the matching substitution is the union of these substitutions. +
  • A record pattern + { r1 = p1 ; ... ; rn = pn } + binds the union of all variables bound in the subpatterns + p1,...,pn. + It matches any value + { r1 = V1 ; ... ; rn = Vn ; ...} + where each pi# matches Vi, + and the matching substitution is the union of these substitutions. +
  • A variable pattern x + (identifier other than parameter constructor) + binds the variable x. + It matches any value V, with the substitution {x = V}. +
  • The wild card _ binds no variables. + It matches any value, with the empty substitution. +
  • A disjunctive pattern p | q binds the intersection of + the variables bound by p and q. + It matches anything that + either p or q matches, with the first substitution starting + with p matches, from which those + variables that are not bound by both patterns are removed. +
  • A negative pattern - p binds no variables. + It matches anything that p does not match, with the empty + substitution. +
  • An alias pattern x @ p binds x and all the variables + bound by p. It matches any value V that p matches, with + the same substition extended by {x = V}. +
+ +

+The following patterns are only available for the type Str: +

+
    +
  • A string literal pattern, e.g. "s", binds no variables. + It matches the same string, with the empty substitution. +
  • A concatenation pattern, p + q, + binds the union of variables bound by p and q. + It matches any string that consists + of a prefix matching p and a suffix matching q, + with the union of substitutions corresponding to the first match (see below). +
  • A repetition pattern p* binds no variables. + It matches any string that can be decomposed + into strings that match p, with the empty substitution. +
+ +

+The following pattern is only available for the types Integer +and Ints n: +

+
    +
  • An integer literal pattern, e.g. 214, binds no variables. + It matches the same integer, with + the empty substitution. +
+ +

+All patterns must be linear: the same pattern variable may occur +only once in them. This is what makes it straightforward to speak +about unions of binding sets and substitutions. +

+

+Pattern matching is performed in the order in which the branches +appear in the source code: the branch of the first matching pattern is followed. +In concrete syntax, the type checker reject sets of patterns that are +not exhaustive, and warns for completely overshadowed patterns. +It also checks the type correctness of patterns with respect to the +argument type. In abstract syntax, only type correctness is checked, +no exhaustiveness or overshadowing. +

+

+It follows from the definition of record pattern matching +that it can utilize partial records: the branch +

+
+    {g = Fem} => t
+
+

+in a table of type {g : Gender ; n : Number} => T means the same as +

+
+    {g = Fem ; n = _} => t
+
+

+Variables in regular expression patterns +are always bound to the first match, which is the first +in the sequence of binding lists. For example: +

+
    +
  • x + "e" + y matches "peter" with x = "p", y = "ter" +
  • x + "er"* matches "burgerer" with x = "burg" +
+ + +

Free variation

+

+An expressions of the form +

+variants {t1 ; ... ; tn} +
+where all ti are of the same type T, has itseld type T. +This expression presents ti,...,tn as being in free variation: +the choice between them is not determined by semantics or parameters. +A limiting case is +
+variants {} +
+which encodes a rule saying that there is no way to express a certain +thing, e.g. that a certain inflectional form does not exist. +

+

+A common wisdom in linguistics is that "there is no free variation", which +refers to the situation where all aspects are taken into account. For +instance, the English negation contraction could be expressed as free variation, +

+
+    variants {"don't" ; "do" ++ "not"}
+
+

+if only semantics is taken into account, but if stylistic aspects are included, +then the proper formulation might be with a parameter distinguishing between +informal and formal style: +

+
+    case style of {Informal => "don't" ; Formal => "do" ++ "not"}
+
+

+Since there is not way to choose a particular element from a ``variants` list, +free variants is normally not adequate in libraries, nor in grammars meant for +natural language generation. In application grammars +meant to parse user input, free variation is a way to avoid cluttering the +abstract syntax with semantically insignificant distinctions and even to +tolerate some grammatical errors. +

+

+Permitting variants in all types involves a major modification of the +semantics of GF expressions. All computation rules have to be lifted to +deal with lists of expressions and values. For instance, +

+t ! variants {t1 ; ... ; tn} ==> +variants {t ! t1 ; ... ; t ! tn} +
+This is done in such a way that +variation does not distribute to records (or other product-like structures). +For instance, variants of records, +

+
+    variants {{s = "Auto" ; g = Neutr} ; {s = "Wagen" ; g = Masc}}
+
+

+is not the same as a record of variants, +

+
+    {s = variants {"Auto" ; "Wagen"} ; g = variants {Neutr ; Masc}}
+
+

+Variants of variants are flattened, +

+variants {...; variants {t1 ;...; tn} ;...} +==> +variants {...; t1 ;...; tn ;...} +
+and singleton variants are eliminated, +
+variants {t} ==> t +
+

+ +

Local definitions

+

+A local definition, i.e. a let expression has the form +

+let x : T = t in e +
+The type of x must be T, which also has to be the type of t. +Computation is performed by substituting t for x in e: +
+let x : T = t in e ==> e {x = t} +
+As syntactic sugar, the type can be omitted if the type checker is +able to infer it: +
+let x = t in e +
+It is possible to compress several local definitions into one block: +
+let x : T = t ; y : U = u in e +=== +let x : T = t in let y : U = u in e +
+Another notational variant is a definition block appearing after the main +expression: +
+e where {...} === let {...} in e +
+Curly brackets are obligatory in the where form, and can +also be optionally used in the let form. +

+

+Since a block of definitions is treated as syntactic sugar +for a nested let expression, a constant must be defined before it +is used: the scope is not mutual, as in a module body. +Furthermore, unlike in lin and oper definitions, it is not possible +to bind variables on the left of the equality sign. +

+ +

Function applications in concrete syntax

+

+ +

+

+Fully compiled concrete syntax may not include expressions of function types +except on the outermost level of lin rules, as defined here. +However, +in the source code, and especially in oper definitions, functions +are the main vehicle of code reuse and abstraction. Thus function types and +functions follow the same rules as in abstract syntax, as specified +here. In +particular, the application of a lambda abstract is computed by beta conversion. +

+

+To ensure the elimination of functions, GF uses a special computation rule +for pushing function applications inside tables, since otherwise run-time +variables could block their applications: +

+(table {p1 => f1 ; ... ; + pn => fn } ! e) a + ==> + table {p1 => f1 a ; ... ; + pn => fn a} ! e +
+Also parameter constructors with non-empty contexts, as defined +here, +result in expressions in application form. These expressions are never +a problem if their arguments are just constructors, because they can then +be translated to integers corresponding to the position of the expression +in the enumaration of the values of its type. +However, a constructor +applied to a run-time variable may need to be converted as follows: +
+C...x... ==> case x of {_ => C...x} +
+The resulting expression, when processed by table expansion as explained +here, +results in C being applied to just values of the type of x, and the +application thereby disappears. +

+ +

Reusing top-level grammars as resources

+

+ +

+

+This section is valid for GF 3.0, which abandons the "lock field" +discipline of GF 2.8. +

+

+As explained here, +abstract syntax modules can be opened as interfaces +and concrete syntaxes as their instances. This means that judgements are, +as it were, translated in the following way: +

+
    +
  • cat C G ===> oper C : Type +
  • fun f : T ===> oper f : T +
  • lincat C = T ===> oper C : Type = C +
  • lin f = t ===> oper f = t +
+ +

+Notice that the value T of lincat definitions is not disclosed +in the translation. This means that the type C remains abstract: the +only ways of building an object of type C are the operations f +obtained from fun and lin rules. +

+

+The purpose of keeping linearization types abstract is to enforce +grammar checking via type checking. This means that any well-typed +operation application is also well-typed in the sense of the original +grammar. If the types were disclosed, then we could for instance easily +confuse all categories that have the linearization +type {s : Str}. Yet another reason is that revealing the types +makes it impossible for the library programmers to change their type +definitions afterwards. +

+

+Library writers may occasionally want to have access to the values of +linearization types. The way to make it possible is to add an extra +construction operation to a module in which the linearization type +is available: +

+
+    oper MkC : T -> C = \x -> x
+
+

+In object-oriented terms, the type C itself is protected, whereas +MkC is a public constructor of C. Of course, it is possible to +make these constructors overloaded (concept explained here), +to enable easy access to special cases. +

+ +

Predefined concrete syntax types

+

+ +

+

+The following concrete syntax types are predefined: +

+
    +
  • Str, the type of tokens and token lists (defined here) +
  • Integer, the type of nonnegative integers +
  • Ints n, the type of integers from 0 to n +
  • Type, the type of (concrete syntax) types +
  • PType, the type of parameter types +
+ +

+The last two types are, in a way, extended by user-written grammars, +since new parameter types can be defined in the way shown here, +and every paramater type is also a type. From the point of view of the values +of expressions, however, a param declaration does not extend +PType, since all parameter types get compiled to initial +segments of integers. +

+

+Notice the difference between the concrete syntax types +Str and Integer on the one hand, and the abstract +syntax categories String and Int, on the other. +As concrete syntax types, the latter are treated in +the same way as any reused categories: their objects +can be formed by using syntax trees (string and integer +literals). +

+

+The type name Integer replaces in GF 3.0 the name Int, +to avoid confusion with the abstract syntax type and to be analogous +with the Str vs. String distinction. +

+ +

Predefined concrete syntax operations

+

+The following predefined operations are defined in the resource module +prelude/Predefined.gf. Their implementations are defined as +a part of the GF grammar compiler. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
operationtypeexplanation
PBoolPTypePTrue | PFalse
ErrorTypethe empty type
IntTypethe type of integers
IntsInteger -> Typethe type of integers from 0 to n
errorStr -> Errorforms error message
lengthStr -> Intlength of string
dropInteger -> Str -> Strdrop prefix of length
takeInteger -> Str -> Strtake prefix of length
tkInteger -> Str -> Strdrop suffix of length
dpInteger -> Str -> Strtake suffix of length
eqIntInteger -> Integer -> PBooltest if equal integers
lessIntInteger -> Integer -> PBooltest order of integers
plusInteger -> Integer -> Integeradd integers
eqStrStr -> Str -> PBooltest if equal strings
occurStr -> Str -> PBooltest if occurs as substring
occursStr -> Str -> PBooltest if any char occurs
show(P : Type) -> P -> Strconvert param to string
read(P : Type) -> Str -> Pconvert string to param
toStr(L : Type) -> L -> Strfind the "first" string
+ +

+

+Compilation eliminates these operations, and they may therefore not +take arguments that depend on run-time variables. +

+

+The module Predef is included in the opens list of all +modules, and therefore does not need to be opened explicitly. +

+ +

Flags and pragmas

+ +

Some flags and their values

+

+ +

+

+The flag coding in concrete syntax sets the character encoding +used in the grammar. Internally, GF uses unicode, and .gfcc files +are always written in UTF8 encoding. The presence of the flag +coding=utf8 prevents GF from encoding an already encoded +file. +

+

+The flag lexer in concrete syntax sets the lexer, +i.e. the processor that turns +strings into token lists sent to the parser. Some GF implementations +support the following lexers. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
lexerdescription
words(default) tokens are separated by spaces or newlines
literalslike words, but integer and string literals recognized
charseach character is a token
codeprogram code conventions (uses Haskell's lex)
textwith conventions on punctuation and capital letters
codelitlike code, but recognize literals (unknown words as strings)
textlitlike text, but recognize literals (unknown words as strings)
+ +

+

+The flag startcat in abstract syntax sets the default start category for +parsing, random generation, and any other grammar operation that depends +on category. Its legal values are the categories defined or inherited in +the abstract syntax. +

+

+The flag unlexer in concrete syntax sets the lexer, +i.e. the processor that turns +token lists obrained from the linearizer to strings. Some GF implementations +support the following unlexers. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
unlexerdescription
unwords(default) space-separated token list
textformat as text: punctuation, capitals, paragraph <p>
codeformat as code (spacing, indentation)
textlitlike text, but remove string literal quotes
codelitlike code, but remove string literal quotes
concatremove all spaces
+ +

+ +

Compiler pragmas

+

+Compiler pragmas are a special form of comments prefixed with --#. +Currently GF interprets the following pragmas. +

+ + + + + + + + + +
pragmaexplanation
-path=PATHpath list for searching modules
+ +

+

+For instance, the line +

+
+    --# -path=.:present:prelude:/home/aarne/GF/tmp
+
+

+in the top of FILE.gf causes the GF compiler, when invoked on FILE.gf, +to search through the current directory (.) and the directories +present, prelude, and /home/aarne/GF/tmp, in this order. +If a directory DIR is not found relative to the working directory, +also $(GF_LIB_PATH)/DIR is searched. +

+ +

Alternative grammar input formats

+

+While the GF language as specified in this document is the most versatile +and powerful way of writing GF grammars, there are several other formats +that a GF compiler may make available for users, either to get started +with small grammars or to semiautomatically convert grammars from other +formats to GF. Here are the ones supported by GF 2.8 and 3.0. +

+ +

Old GF without modules

+

+ +

+

+Before GF compiler version 2.0, there was no module system, and +all kinds of judgement could be written in all files, without +any headers. This format is still available, and the compiler +(version 2.8) detects automatically if a file is in the current +or the old format. However, the old format is not recommended +because of pure modularity and missing separate compilation, +and also because libraries are not available, since the old +and the new format cannot be mixed. With version 2.8, grammars +in the old format can be converted to modular grammar with the +command +

+
+    > import -o FILE.gf
+
+

+which rewrites the grammar divided into three files: +an abstract, a concrete, and a resource module. +

+ +

Context-free grammars

+

+A quick way to write a GF grammar is to use the context-free format, +also known as BNF. Files of this form are recognized by the suffix +.cf. Rules in these files have the form +

+Label . Cat ::= (String | Cat)* ; +
+where Label and Cat are identifiers and String quoted strings. +

+

+There is a shortcut form generating labels automatically, +

+Cat ::= (String | Cat)* ; +
+In the shortcut form, vertical bars (|) can be used to give +several right-hand-sides at a time. An empty right-hand side +means the singleton of an empty sequence, and not an empty union. +

+

+Just like old-style GF files (previous section), contex-free grammar +files can be converted to modular GF by using the -o option to +the compiler in GF 2.8. +

+ +

Extended BNF grammars

+

+Extended BNF (FILE.ebnf) +goes one step further from the shortcut notation of previous section. +The rules have the form +

+Cat ::= RHS ; +
+where an RHS can be any regular expression +built from quoted strings and category symbols, in the following ways: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RHS itemexplanation
Catnonterminal
Stringterminal
RHS RHSsequence
RHS | RHSalternatives
RHS ?optional
RHS *repetition
RHS +non-empty repetition|
+ +

+

+Parentheses are used to override standard precedences, where +| binds weaker than sequencing, which binds weaker than the unary operations. +

+

+The compiler generates not only labels, but also new categories corresponding +to the regular expression combinations actually in use. +

+

+Just like .cf files (previous section), .ebnf +files can be converted to modular GF by using the -o option to +the compiler in GF 2.8. +

+ +

Example-based grammars

+

+Example-based grammars (.gfe) provide a way to use +resource grammar libraries without having to know the names +of functions in them. The compiler works as a preprocessor, +saving the result in a (.gf) file, which can be compiled +as usual. +

+

+If a library is implemented as an abstract and concrete syntax, +it can be used for parsing. Calls of library functions can therefore +be formed by parsing strings in the library. GF has an expression +format for this, +

+in C String +
+where C is the category in which to parse (it can be qualified by +the module name) and the string is the input to parser. Expressions +of this form are replaced by the syntax trees that result. These +trees are always type-correct. If several parses are found, all but +the first one are given in comments. +

+

+Here is an example, from GF/examples/animal/: +

+
+    --# -resource=../../lib/present/LangEng.gfc
+    --# -path=.:present:prelude
+  
+    incomplete concrete QuestionsI of Questions = open Lang in {
+      lincat
+        Phrase = Phr ;
+        Entity = N ;
+        Action = V2 ;
+      lin
+        Who  love_V2 man_N           = in Phr "who loves men" ;
+        Whom man_N love_V2           = in Phr "whom does the man love" ;
+        Answer woman_N love_V2 man_N = in Phr "the woman loves men" ;
+    }
+
+

+The resource pragma shows the grammar that is used for parsing +the examples. +

+

+Notice that the variables love_V2, man_N, etc, are +actually constants in the library. In the resulting rules, such as +

+
+    lin Whom = \man_N -> \love_V2 -> 
+      PhrUtt NoPConj (UttQS (UseQCl TPres ASimul PPos 
+        (QuestSlash whoPl_IP (SlashV2 (DetCN (DetSg (SgQuant 
+          DefArt)NoOrd)(UseN man_N)) love_V2)))) NoVoc ;
+
+

+those constants are nonetheless treated as variables, following +the normal binding conventions, as stated here. +

+ +

The grammar of GF

+

+The following grammar is actually used in the parser of GF, although we have +omitted +some obsolete rules still included in the parser for backward compatibility +reasons. +

+

+This document was automatically generated by the BNF-Converter. It was generated together with the lexer, the parser, and the abstract syntax module, which guarantees that the document matches with the implementation of the language (provided no hand-hacking has taken place). +

+ +

The lexical structure of GF

+ +

Identifiers

+

+Identifiers Ident are unquoted strings beginning with a letter, +followed by any combination of letters, digits, and the characters _ ' +reserved words excluded. +

+ +

Literals

+

+Integer literals Integer are nonempty sequences of digits. +

+

+String literals String have the form +"x"}, where x is any sequence of any characters +except " unless preceded by \. +

+

+Double-precision float literals Double have the structure +indicated by the regular expression digit+ '.' digit+ ('e' ('-')? digit+)? i.e.\ +two sequences of digits separated by a decimal point, optionally +followed by an unsigned or negative exponent. +

+ +

Reserved words and symbols

+

+The set of reserved words is the set of terminals appearing in the grammar. Those reserved words that consist of non-letter characters are called symbols, and they are treated in a different way from those that are similar to identifiers. The lexer follows rules familiar from languages like Haskell, C, and Java, including longest match and spacing conventions. +

+

+The reserved words used in GF are the following: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PTypeStrStrsType
abstractcasecatconcrete
datadefflagsfun
inincompleteinstanceinterface
letlinlincatlindef
ofopenoperparam
preprintnameresourcestrs
tabletransfervariantswhere
with
+ +

+

+The symbols used in GF are the following: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
;=:->
{}**,
()[]
-.|?
<>@!
*+++\
=>_$/
+ +

+ +

Comments

+

+Single-line comments begin with --.Multiple-line comments are enclosed with {- and -}. +

+ +

The syntactic structure of GF

+

+Non-terminals are enclosed between < and >. +The symbols -> (production), | (union) +and eps (empty rule) belong to the BNF notation. +All other symbols are terminals. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Grammar->[ModDef]
[ModDef]->eps
|ModDef [ModDef]
ModDef->ModDef ;
|ComplMod ModType = ModBody
ModType->abstract Ident
|resource Ident
|interface Ident
|concrete Ident of Ident
|instance Ident of Ident
|transfer Ident : Open -> Open
ModBody->Extend Opens { [TopDef] }
|[Included]
|Included with [Open]
|Included with [Open] ** Opens { [TopDef] }
|[Included] ** Included with [Open]
|[Included] ** Included with [Open] ** Opens { [TopDef] }
[TopDef]->eps
|TopDef [TopDef]
Extend->[Included] **
|eps
[Open]->eps
|Open
|Open , [Open]
Opens->eps
|open [Open] in
Open->Ident
|( QualOpen Ident )
|( QualOpen Ident = Ident )
ComplMod->eps
|incomplete
QualOpen->eps
[Included]->eps
|Included
|Included , [Included]
Included->Ident
|Ident [ [Ident] ]
|Ident - [ [Ident] ]
Def->[Name] : Exp
|[Name] = Exp
|Name [Patt] = Exp
|[Name] : Exp = Exp
TopDef->cat [CatDef]
|fun [FunDef]
|data [FunDef]
|def [Def]
|data [DataDef]
|param [ParDef]
|oper [Def]
|lincat [PrintDef]
|lindef [Def]
|lin [Def]
|printname cat [PrintDef]
|printname fun [PrintDef]
|flags [FlagDef]
CatDef->Ident [DDecl]
|[ Ident [DDecl] ]
|[ Ident [DDecl] ] { Integer }
FunDef->[Ident] : Exp
DataDef->Ident = [DataConstr]
DataConstr->Ident
|Ident . Ident
[DataConstr]->eps
|DataConstr
|DataConstr | [DataConstr]
ParDef->Ident = [ParConstr]
|Ident = ( in Ident )
|Ident
ParConstr->Ident [DDecl]
PrintDef->[Name] = Exp
FlagDef->Ident = Ident
[Def]->Def ;
|Def ; [Def]
[CatDef]->CatDef ;
|CatDef ; [CatDef]
[FunDef]->FunDef ;
|FunDef ; [FunDef]
[DataDef]->DataDef ;
|DataDef ; [DataDef]
[ParDef]->ParDef ;
|ParDef ; [ParDef]
[PrintDef]->PrintDef ;
|PrintDef ; [PrintDef]
[FlagDef]->FlagDef ;
|FlagDef ; [FlagDef]
[ParConstr]->eps
|ParConstr
|ParConstr | [ParConstr]
[Ident]->Ident
|Ident , [Ident]
Name->Ident
|[ Ident ]
[Name]->Name
|Name , [Name]
LocDef->[Ident] : Exp
|[Ident] = Exp
|[Ident] : Exp = Exp
[LocDef]->eps
|LocDef
|LocDef ; [LocDef]
Exp6->Ident
|Sort
|String
|Integer
|Double
|?
|[ ]
|data
|[ Ident Exps ]
|[ String ]
|{ [LocDef] }
|< [TupleComp] >
|< Exp : Exp >
|( Exp )
Exp5->Exp5 . Label
|Exp6
Exp4->Exp4 Exp5
|table { [Case] }
|table Exp6 { [Case] }
|table Exp6 [ [Exp] ]
|case Exp of { [Case] }
|variants { [Exp] }
|pre { Exp ; [Altern] }
|strs { [Exp] }
|Ident @ Exp6
|Exp5
Exp3->Exp3 ! Exp4
|Exp3 * Exp4
|Exp3 ** Exp4
|Exp4
Exp1->Exp2 + Exp1
|Exp2
Exp->Exp1 ++ Exp
|\ [Bind] -> Exp
|\ \ [Bind] => Exp
|Decl -> Exp
|Exp3 => Exp
|let { [LocDef] } in Exp
|let [LocDef] in Exp
|Exp3 where { [LocDef] }
|in Exp5 String
|Exp1
Exp2->Exp3
[Exp]->eps
|Exp
|Exp ; [Exp]
Exps->eps
|Exp6 Exps
Patt2->_
|Ident
|Ident . Ident
|Integer
|Double
|String
|{ [PattAss] }
|< [PattTupleComp] >
|( Patt )
Patt1->Ident [Patt]
|Ident . Ident [Patt]
|Patt2 *
|Ident @ Patt2
|- Patt2
|Patt2
Patt->Patt | Patt1
|Patt + Patt1
|Patt1
PattAss->[Ident] = Patt
Label->Ident
|$ Integer
Sort->Type
|PType
|Str
|Strs
[PattAss]->eps
|PattAss
|PattAss ; [PattAss]
[Patt]->Patt2
|Patt2 [Patt]
Bind->Ident
|_
[Bind]->eps
|Bind
|Bind , [Bind]
Decl->( [Bind] : Exp )
|Exp4
TupleComp->Exp
PattTupleComp->Patt
[TupleComp]->eps
|TupleComp
|TupleComp , [TupleComp]
[PattTupleComp]->eps
|PattTupleComp
|PattTupleComp , [PattTupleComp]
Case->Patt => Exp
[Case]->Case
|Case ; [Case]
Altern->Exp / Exp
[Altern]->eps
|Altern
|Altern ; [Altern]
DDecl->( [Bind] : Exp )
|Exp6
[DDecl]->eps
|DDecl [DDecl]
+ +

+ + + + diff --git a/doc/gf-tutorial.html b/doc/gf-tutorial.html new file mode 100644 index 000000000..1e6d961b8 --- /dev/null +++ b/doc/gf-tutorial.html @@ -0,0 +1,7952 @@ + + + + + +Grammatical Framework Tutorial + +

Grammatical Framework Tutorial

+ +Aarne Ranta
+Draft, November 2007 +
+ +

+
+

+ + +

+
+

+

+

Overview

+

+

+This tutorial gives a hands-on introduction to grammar writing in GF. +It has been written for all programmers +who want to learn to write grammars in GF. +It will go through the programming concepts of GF, and also +explain, without presupposing them, the main ingredients of GF: +linguistics, functional programming, and type theory. +This knowledge will be introduced as a part of grammar writing +practice. +Thus the tutorial should be accessible to anyone who has some +previous experience from any programming language; the basics +of using computers are also presupposed, e.g. the use of +text editors and the management of files. +

+

+We start in the second chapter +by building a "Hello World" grammar, which covers greetings +in three languages: English (hello world), +Finnish (terve maailma), and Italian (ciao mondo). +This multilingual grammar is based on the most central idea of GF: +the distinction between abstract syntax +(the logical structure) and concrete syntax (the +sequence of words). +

+

+From the "Hello World" example, we proceed +in the third chapter +to a larger grammar for the domain of food. +In this grammar, you can say things like +

+this Italian cheese is delicious +
+in English and Italian. This grammar illustrates how translation is +more than just replacement of words. For instance, the order of +words may have to be changed: +
+Italian cheese +

+

+formaggio italiano +

+Moreover, words can have different forms, and which forms +they have vary from language to language. For instance, +Italian adjectives usually have four forms where English +has just one: +
+delicious (wine, wines, pizza, pizzas) +

+

+vino delizioso, vini deliziosi, pizza deliziosa, pizze deliziose +

+The morphology of a language describes the +forms of its words, and the basics of implementing morphology and +integrating it with syntax are covered in the fourth chapter. +

+

+The complete description of morphology and syntax in natural +languages is in GF preferably left to the resource grammar library. +Its use is therefore an important part of GF programming, and +it is covered in the fifth chapter. How to contribute to resource +grammars as an author will only be covered in Part III; +however, the tutorial does go through all the +programming concepts of GF, including those involved in +resource grammars. +

+

+In addition to multilinguality, semantics is an important aspect of GF +grammars. The "purely linguistic" aspects (morphology and syntax) belong to +the concrete syntax part of GF, whereas semantics is expressed in the abstract +syntax. After the presentation of concrete syntax constructs, we proceed +in the sixth chapter to the enrichment of abstract syntax with dependent types, +variable bindings, and semantic definitions. +the seventh chapter concludes the tutorial by technical tips for implementing formal +languages. It will also illustrate the close relation between GF grammars +and compilers by actually implementing a small compiler from C-like statements +and expressions to machine code similar to Java Virtual Machine. +

+

+English and Italian are used as example languages in many grammars. +Of course, we will not presuppose that the reader knows any Italian. +We have chosen Italian because it has a rich structure +that illustrates very well the capacities of GF. +Moreover, even those readers who don't know Italian, will find many of +its words familiar, due to the Latin heritage. +The exercises will encourage the reader to +port the examples to other languages as well; in particular, +it should be instructive for the reader to look at her +own native language from the point of view of writing a grammar +implementation. +

+

+To learn how to write GF grammars is not the only goal of +this tutorial. We will also explain the most important +commands of the GF system, mostly in passing. With these commands, +simple application programs such as translation and +quiz systems, can be built simply by writing scripts for the +GF system. More complicated applications, such as natural-language +interfaces and dialogue systems, moreover require programming in +some general-purpose language; such applications are covered in the eighth chapter. +

+ +

Getting started with GF

+

+ +

+

+In this chapter, we will introduce the GF system and write the first GF grammar, +a "Hello World" grammar. While extremely small, this grammar already illustrates +how GF can be used for the tasks of translation and multilingual +generation. +

+ +

What GF is

+

+We use the term GF for three different things: +

+
    +
  • a system (computer program) used for working with grammars +
  • a programming language in which grammars can be written +
  • a theory about grammars and languages +
+ +

+The relation between these things is obvious: the GF system is an implementation +of the GF programming language, which in turn is built on the ideas of the +GF theory. The main focus of this book is on the GF programming language. +We learn how grammars are written in this language. At the same time, we learn +the way of thinking in the GF theory. To make this all useful and fun, and +to encourage experimenting, we make the grammars run on a computer by +using the GF system. +

+

+A GF program is called a grammar. A grammar is, traditionally, a +definition of a language. From this definition, different language +processing components can be derived: +

+
    +
  • parsing: to analyse the language +
  • linearization: to generate the language +
  • translation: to analyse one language and generate another +
+ +

+A GF grammar is thus a declarative program from which these +procedures can be automatically derived. In general, a GF grammar +is multilingual: it defines many languages and translations between them. +

+ +

Getting the GF system

+

+The GF system is open-source free software, which can be downloaded via the +GF Homepage: +

+gf.digitalgrammars.com +
+There you can download +

+
    +
  • binaries for Linux, Mac OS X, and Windows +
  • source code and documentation +
  • grammar libraries and examples +
+ +

+In particular, many of the examples in this book are included in the +subdirectory examples/tutorial of the source distribution package. +This directory is also available +online. +

+

+If you want to compile GF from source, you need a Haskell compiler. +To compile the interactive editor, you also need a Java compilers. +But normally you don't have to compile anything yourself, and you definitely +don't need to know Haskell or Java to use GF. +

+

+We are assuming the availability of a Unix shell. Linux and Mac OS X users +have it automatically, the latter under the name "terminal". +Windows users are recommended to install Cywgin, the free Unix shell for Windows. +

+ +

Running the GF system

+

+To start the GF system, assuming you have installed it, just type +gf in the Unix (or Cygwin) shell: +

+
+    % gf
+
+

+You will see GF's welcome message and the prompt >. +The command +

+
+    > help
+
+

+will give you a list of available commands. +

+

+As a common convention in this book, we will use +

+
    +
  • % as a prompt that marks system commands +
  • > as a prompt that marks GF commands +
+ +

+Thus you should not type these prompts, but only the characters that +follow them. +

+ +

A "Hello World" grammar

+

+The tradition in programming language tutorials is to start with a +program that prints "Hello World" on the terminal. GF should be no +exception. But our program has features that distinguish it from +most "Hello World" programs: +

+
    +
  • Multilinguality: the message is printed in many languages. +
  • Reversibility: in addition to printing, you can parse the + message and translate it to other languages. +
+ + +

The program: abstract syntax and concrete syntaxes

+

+A GF program, in general, is a multilingual grammar. Its main parts +are +

+
    +
  • an abstract syntax +
  • one or more concrete syntaxes +
+ +

+The abstract syntax defines, in a language-independent way, what meanings +can be expressed in the grammar. In the "Hello World" grammar we want +to express Greetings, where we greet a Recipient, which can be +World or Mum or Friends. Here is the entire +GF code for the abstract syntax: +

+
+    -- a "Hello World" grammar
+    abstract Hello = {
+  
+      flags startcat = Greeting ;
+  
+      cat Greeting ; Recipient ;
+  
+      fun 
+        Hello : Recipient -> Greeting ;
+        World, Mum, Friends : Recipient ;
+    }
+
+

+The code has the following parts: +

+
    +
  • a comment (optional), saying what the module is doing +
  • a module header indicating that it is an abstract syntax + module named Hello +
  • a module body in braces, consisting of +
      +
    • a startcat flag declaration stating that Greeting is the + main category, i.e. the one in which parsing and generation are + performed by default +
    • category declarations stating that Greeting and Recipient + are categories, i.e. types of meanings +
    • function declarations stating what meaning-building functions there + are; these are the function Hello constructing a greeting from a recipient, + as well as the three possible recipients +
    +
+ +

+A concrete syntax defines a mapping from the abstract meanings to their +expressions in a language. We first give an English concrete syntax: +

+
+    concrete HelloEng of Hello = {
+  
+      lincat Greeting, Recipient = {s : Str} ;
+  
+      lin 
+        Hello recip = {s = "hello" ++ recip.s} ;
+        World = {s = "world"} ;
+        Mum = {s = "mum"} ;
+        Friends = {s = "friends"} ;
+    }
+
+

+The major parts of this code are: +

+
    +
  • a module header indicating that it is a concrete syntax of the abstract syntax + Hello, itself named HelloEng +
  • a module body in curly brackets, consisting of +
      +
    • linearization type definitions stating that + Greeting and Recipient are records with a string s +
    • linearization definitions telling what records are assigned to + each of the meanings defined in the abstract syntax; the recipients are + linearized to records containing single words, whereas the Hello greeting + has a function telling that the word hello is prefixed to the string + s contained in the record recip +
    +
+ +

+To make the grammar truly multilingual, we add a Finnish and an Italian concrete +syntax: +

+
+    concrete HelloFin of Hello = {
+      lincat Greeting, Recipient = {s : Str} ;
+      lin 
+        Hello recip = {s = "terve" ++ recip.s} ;
+        World = {s = "maailma"} ;
+        Mum = {s = "äiti"} ;
+        Friends = {s = "ystävät"} ;
+    }
+  
+    concrete HelloIta of Hello = {
+      lincat Greeting, Recipient = {s : Str} ;
+      lin 
+        Hello recip = {s = "ciao" ++ recip.s} ;
+        World = {s = "mondo"} ;
+        Mum = {s = "mamma"} ;
+        Friends = {s = "amici"} ;
+    }
+
+

+Now we have a trilingual grammar usable for translation and +many other tasks, which we will now start experimenting with. +

+ +

Using the grammar in the GF system

+

+In order to compile the grammar in GF, each of the four modules +has to be put into a file named Modulename.gf: +

+
+    Hello.gf  HelloEng.gf  HelloFin.gf  HelloIta.gf
+
+

+The first GF command needed when using a grammar is to import it. +The command has a long name, import, and a short name, i. +When you have started GF (by the shell command gf), you can thus type either +

+
+    > import HelloEng.gf
+
+

+or +

+
+    > i HelloEng.gf
+
+

+to get the same effect. In general, all GF commands have a long and a short name; +short names are convenient when typing commands by hand, whereas long command +names are more readable in scripts, i.e. files that include sequences of commands. +

+

+The effect of import is that the GF system compiles your grammar +into an internal representation, and shows a new prompt when it is ready. +It will also show how much CPU time was consumed: +

+
+    > i HelloEng.gf
+    - compiling Hello.gf...   wrote file Hello.gfc 8 msec
+    - compiling HelloEng.gf...   wrote file HelloEng.gfc 12 msec
+  
+    12 msec
+    >
+
+

+You can now use GF for parsing: +

+
+    > parse "hello world"
+    Hello World
+
+

+The parse (= p) command takes a string +(in double quotes) and returns an abstract syntax tree --- the meaning +of the string as defined in the abstract syntax. +A tree is, in general, something easier than a string +for a machine to understand and to process further, although this +is not so obvious in this simple grammar. The syntax for trees is that +of function application, which in GF is written +

+
+    function argument1 ... argumentn
+
+

+Parentheses are only needed for grouping. For instance, f (a b) is +f applied to the application of a to b. This is different +from f a b, which is f applied to a and b. +

+

+Strings that return a tree when parsed do so in virtue of the grammar +you imported. Try to parse something that is not in grammar, and you will fail +

+
+    > parse "hello dad"
+    Unknown words: dad
+  
+    > parse "world hello"
+    no tree found
+
+

+In the first example, the failure is caused by an unknown word. +In the second example, the combination of words is ungrammatical. +

+

+In addition to parsing, you can also use GF for linearization +(linearize = l). This is the inverse of +parsing, taking trees into strings: +

+
+    > linearize Hello World
+    hello world
+
+

+What is the use of this? Typically not that you type in a tree at +the GF prompt. The utility of linearization comes from the fact that +you can obtain a tree from somewhere else --- for instance, from +a parser. A prime example of this is translation: you parse +with one concrete syntax and linearize with another. Let us +now do this by first importing the Italian grammar: +

+
+    > import HelloIta.gf
+
+

+We can now parse with HelloEng and pipe the result +into linearizing with HelloIta: +

+
+    > parse -lang=HelloEng "hello mum" | linearize -lang=HelloIta
+    ciao mamma
+
+

+Notice that, since there are now two concrete syntaxes read into the +system, the commands use a language flag to indicate +which concrete syntax is used in each operation. If no language flag is +given, the last-imported language is applied. +

+

+To conclude the translation exercise, we import the Finnish grammar +and pipe English parsing into multilingual generation: +

+
+    > parse -lang=HelloEng "hello friends" | linearize -multi
+    terve ystävät
+    ciao amici
+    hello friends
+
+

+

+Exercise. Test the parsing and translation examples shown above, as well as +some other examples, in different combinations of languages. +

+

+Exercise. Extend the grammar Hello.gf and some of the +concrete syntaxes by five new recipients and one new greeting +form. +

+

+Exercise. Add a concrete syntax for some other +languages you might know. +

+

+Exercise. Add a pair of greetings that are expressed in one and the same way in +one language and in two different ways in another. For instance, good morning +and good afternoon in English are both expressed as buongiorno in Italian. +Test what happens when you translate buongiorno to English in GF. +

+

+Exercise. Inject errors in the Hello grammars, for example, leave out +some line, omit a variable in a lin rule, or change the name in one occurrence +of a variable. Inspect the error messages generated by GF. +

+ +

Using grammars from outside GF

+

+A normal "hello world" program written in C is executable from the +Unix shell and print its output on the terminal. This is possible in GF +as well, by using the gf program in a Unix pipe. Invoking gf +can be made with grammar names as arguments, +

+
+    % gf HelloEng.gf HelloFin.gf HelloIta.gf
+
+

+which has the same effect as opening gf and then importing the +grammars. A command can be send to this gf state by piping it from +Unix's echo command: +

+
+    % echo "l -multi Hello Wordl" | gf HelloEng.gf HelloFin.gf HelloIta.gf
+
+

+which will execute the command and then quit. Alternatively, one can write +a script, a file containing the lines +

+
+    import HelloEng.gf
+    import HelloFin.gf
+    import HelloIta.gf
+    linearize -multi Hello World
+
+

+If we name this script hello.gfs, we can do +

+
+    $ gf -batch -s <hello.gfs s
+  
+    ciao mondo
+    terve maailma
+    hello world
+
+

+The options -batch and -s ("silent") remove prompts, CPU time, +and other messages. Writing GF scripts and Unix shell scripts that call +GF is the simplest way to build application programs that use GF grammars. +In the eighth chapter, we will see how to build stand-alone programs that don't need +the GF system to run. +

+

+Exercise. (For Unix hackers.) Write a GF application that reads +an English string from the standard input and writes an Italian +translation to the output. +

+ +

What else can be done with the grammar

+

+Now we have built our first multilingual grammar and seen the basic +functionalities of GF: parsing and linearization. We have tested +these functionalities inside the GF program. In the forthcoming +chapters, we will build larger grammars and can then get more out of +these functionalities. But we will also introduce new ones: +

+
    +
  • morphological analysis: find out the possible inflection forms of words +
  • morphological synthesis: generate all inflection forms of words +
  • random generation: generate random expressions +
  • corpus generation: generate all expressions +
  • treebank generation: generate a list of trees with their linearizations +
  • teaching quizzes: train morphology and translation +
  • multilingual authoring: create a document in many languages simultaneously +
  • speech input: optimize a speech recognition system for a grammar +
+ +

+The usefulness of GF would be quite limited if grammars were +usable only inside the GF system. In the eighth chapter, +we will see other ways of using grammars: +

+
    +
  • compile them to new formats, such as speech recognition grammars +
  • embed them in Java and Haskell programs +
  • build applications using compilation and embedding: +
      +
    • voice commands +
    • spoken language translators +
    • dialogue systems +
    • user interfaces +
    • localization: parametrize the messages printed by a program + to support different languages +
    +
+ +

+All GF functionalities, both those inside the GF program and those +ported to other environments, +are of course already applicable to the simplest of grammars, +such as the Hello grammars presented above. But the main focus +of this tutorial will be on grammar writing. Thus we will show +how larger and more expressive grammars can be built by using +the constructs of the GF programming language, before entering the +applications. +

+ +

Summary of GF language features

+

+As the last section of each chapter, we will give a summary of the GF language +features covered in the chapter. The presentation is rather technical and intended +as a reference for later use, rather than to be read at once. The summaries +may cover some new features, which complement the discussion in the main chapter. +

+ +

Modules

+

+A GF grammar consists of modules, +into which judgements are grouped. The most important +module forms are +

+
    +
  • abstract A = {...} , abstract syntax A with judgements in + the module body {...}. +
  • concrete C of A = {...}, concrete syntax C of the + abstract syntax A, with judgements in the module body {...}. +
+ +

+Each module is written in a file named Modulename.gf. +

+ +

Judgements

+

+ +

+

+Rules in a module body are called judgements. Keywords such as +fun and lin are used for distinguishing between +judgement forms. Here is a summary of the most important +judgement forms, which we have considered by now: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
formreadingmodule type
cat CC is a categoryabstract
fun f : Af is a function of type Aabstract
lincat C = Tcategory C has linearization type Tconcrete
lin f x1 ... xn = tfunction f has linearization tconcrete
flags p = vflag p has value vany
+ +

+

+Both abstract and concrete modules may moreover contain comments of the forms +

+
    +
  • -- anything until a newline +
  • {- anything except hyphen followed by closing brace -} +
+ +

+Judgements are terminated by semicolons. Shorthands permit the sharing of +the keyword in subsequent judgements, +

+
+    cat C ; D ; ===   cat C ; cat D ; 
+
+

+and of the right-hand-side in subsequent judgements of the same form +

+
+    fun f, g : A ;  ===  fun f : A ; g : A ; 
+
+

+We will use the symbol === to indicate syntactic sugar when +speaking about GF. Thus it is not a symbol of the GF language. +

+

+Each judgement declares a name, which is an identifier. +An identifier is a letter followed by a sequence of letters, digits, and +characters ' or _. Each identifier can only be +defined once in the same module (that is, as next to the judgement keyword; +local variables such as those in lin judgemenrs can be +reused in other judgements). +

+

+Names are in scope in the rest of the module, i.e. usable in the other +judgements of the module (subject to type restrictions, of course). Also +the name of the module is an identifier in scope. +

+

+The order of judgements in a module is free. In particular, an identifier +need not be declared before it is used. +

+ +

Types and terms

+

+A type in an abstract syntax are either a basic type, +i.e. one introduced in a cat judgement, or a +function type of the form +

+
+    A1 -> ... -> An -> A
+
+

+where each of A1, ..., An, A is a basic type. +The last type in the arrow-separated sequence +is the value type of the function type, and the earlier types are +its argument types. +

+

+In a concrete syntax, the available types include +

+
    +
  • the type of token lists, Str +
  • record types of form { r1 : T1 ; ... ; rn : Tn } +
+ +

+Token lists are often briefly called strings. +

+

+Each semi-colon separated part in a record type is called a +field. The identifier introduced by the left-hand-side of a field +is called a label. +

+

+A term in abstract syntax is a function application of form +

+
+    f a1 ... an
+
+

+where f is a function declared in a fun judgement and a1 ... an +are terms. These terms are also called abstract syntax trees, or just +trees. +The tree above is well-typed and has the type A, if +

+
+    f : A1 -> ... -> An -> A
+
+

+and each ai has type an. +

+

+A term used in concrete syntax has one the forms +

+
    +
  • quoted string: "foo", of type Str +
  • concatenation of strings: "foo" ++ "bar", +
  • record: { r1 = t1 ; ... ; rn = Tn }, + of type { r1 : R1 ; ... ; rn : Rn } +
  • projection t.r of a term t that has a record type, + with the record label r; the projection has the corresponding record + field type +
  • argument variable x bound by the left-hand-side of a lin rule, + of the corresponding linearization type +
+ +

+Each quoted string is treated as one token, and strings concatenated by +++ are treated as separate tokens. Tokens are, by default, written with +a space in between. This behaviour can be changed by lexer and unlexer +flags, as will be explained later "Rseclexing. Therefore it is usually +not correct to have a space in a token. Writing +

+
+    "hello world"
+
+

+in a grammar would give the parser the task to find a token with a space +in it, rather than two tokens "hello" and "world". If the latter is +what is meant, it is possible to use the shorthand +

+
+    ["hello world"]  ===  "hello" ++ "world"
+
+

+The empty string is denoted by [] or, equivalently, `` or ``[]. +

+ +

Type checking

+

+An important functionality of the GF system is static type checking. +This means that the grammars are controlled to be well-formed, so that all +run-time errors are eliminated. The main type checking principles are the +following: +

+
    +
  • a concrete syntax must define the lincat of each cat and a lin + for each fun in the abstract syntax that it is "of" +
  • lin rules are type checked with respect to the lincat and fun + rules +
  • terms have types as defined in the previous section +
+ + +

Designing a grammar for complex phrases

+

+ +

+

+In this chapter, we will write a grammar that has much more structure than +the Hello grammar. We will look at how the abstract syntax +is divided into suitable categories, and how infinitely many +phrases can be generated by using recursive rules. We will also +introduce modularity by showing how a grammar can be +divided into modules, and how functional programming +can be used to share code in and among modules. +

+ +

The abstract syntax Food

+

+We will write a grammar that +defines a set of phrases usable for speaking about food: +

+
    +
  • the start category is Phrase +
  • a Phrase can be built by assigning a Quality to an Item + (e.g. this cheese is Italian) +
  • anItem are build from a Kind by prefixing this or that + (e.g. this wine) +
  • a Kind is either atomic (e.g. cheese), or formed + qualifying a given Kind with a Quality (e.g. Italian cheese) +
  • a Quality is either atomic (e.g. Italian, + or built by modifying a given Quality with the word very (e.g. very warm) +
+ +

+These verbal descriptions can be expressed as the following abstract syntax: +

+
+    abstract Food = {
+  
+      flags startcat = Phrase ;
+  
+      cat
+        Phrase ; Item ; Kind ; Quality ;
+  
+      fun
+        Is : Item -> Quality -> Phrase ;
+        This, That : Kind -> Item ;
+        QKind : Quality -> Kind -> Kind ;
+        Wine, Cheese, Fish : Kind ;
+        Very : Quality -> Quality ;
+        Fresh, Warm, Italian, Expensive, Delicious, Boring : Quality ;
+    }
+
+

+In this abstract syntax, we can build Phrases such as +

+
+    Is (This (QKind Delicious (QKind Italian Wine))) (Very (Very Expensive))
+
+

+In the English concrete syntax, we will want to linearize this into +

+
+    this delicious Italian wine is very very expensive
+
+

+ +

The concrete syntax FoodEng

+

+The English concrete syntax gives no surprises: +

+
+    concrete FoodEng of Food = {
+  
+      lincat
+        Phrase, Item, Kind, Quality = {s : Str} ;
+  
+      lin
+        Is item quality = {s = item.s ++ "is" ++ quality.s} ;
+        This kind = {s = "this" ++ kind.s} ;
+        That kind = {s = "that" ++ kind.s} ;
+        QKind quality kind = {s = quality.s ++ kind.s} ;
+        Wine = {s = "wine"} ;
+        Cheese = {s = "cheese"} ;
+        Fish = {s = "fish"} ;
+        Very quality = {s = "very" ++ quality.s} ;
+        Fresh = {s = "fresh"} ;
+        Warm = {s = "warm"} ;
+        Italian = {s = "Italian"} ;
+        Expensive = {s = "expensive"} ;
+        Delicious = {s = "delicious"} ;
+        Boring = {s = "boring"} ;
+    }  
+
+

+Let us test how the grammar works in parsing: +

+
+    > import FoodEng.gf
+    > parse "this delicious wine is very very Italian"
+    Is (This (QKind Delicious Wine)) (Very (Very Italian))
+
+

+We can also try parsing in other categories than the startcat, +by setting the command-line cat flag: +

+
+    p -cat=Kind "very Italian wine"
+    QKind (Very Italian) Wine
+
+

+

+Exercise. Extend the Food grammar by ten new food kinds and +qualities, and run the parser with new kinds of examples. +

+

+Exercise. Add a rule that enables question phrases of the form +is this cheese Italian. +

+

+Exercise. Enable the optional prefixing of +phrases with the words "excuse me but". Do this in such a way that +the prefix can occur at most once. +

+ +

Commands for testing grammars

+ +

Generating trees and strings

+

+When we have a grammar above a trivial size, especially a recursive +one, we need more efficient ways of testing it than just by parsing +sentences that happen to come to our minds. One way to do this is +based on automatic generation, which can be either +random generation or exhaustive generation. +

+

+Random generation (generate_random = gr) is an operation that +builds a random tree in accordance with an abstract syntax: +

+
+    > generate_random
+    Is (This (QKind Italian Fish)) Fresh
+
+

+By using a pipe, random generation can be fed into linearization: +

+
+    > generate_random | linearize
+    this Italian fish is fresh
+
+

+Random generation is a good way to test a grammar. It can also give results +that are surprising, which shows how fast we lose intuition +when we write complex grammars. +

+

+By using the number flag, several trees can be generated +in one command: +

+
+    > gr -number=10 | l
+    that wine is boring
+    that fresh cheese is fresh
+    that cheese is very boring
+    this cheese is Italian
+    that expensive cheese is expensive
+    that fish is fresh
+    that wine is very Italian
+    this wine is Italian
+    this cheese is boring
+    this fish is boring
+
+

+To generate all phrases that a grammar can produce, +GF provides the command generate_trees = gt. +

+
+    > generate_trees | l
+    that cheese is very Italian
+    that cheese is very boring
+    that cheese is very delicious
+    that cheese is very expensive
+    that cheese is very fresh
+    ...
+    this wine is expensive
+    this wine is fresh
+    this wine is warm
+  
+
+

+We get quite a few trees but not all of them: only up to a given +depth of trees. The default depth is 3; the depth can be +set by using the depth flag: +

+
+    > generate_trees -depth=5 | l
+
+

+Other options to the generation commands (like all commands) can be seen +by GF's help = h command: +

+
+    > help gr
+    > help gt
+
+

+

+Exercise. If the command gt generated all +trees in your grammar, it would never terminate. Why? +

+

+Exercise. Measure how many trees the grammar gives with depths 4 and 5, +respectively. Hint. You can +use the Unix word count command wc to count lines. +

+ +

More on pipes; tracing

+

+A pipe of GF commands can have any length, but the "output type" +(either string or tree) of one command must always match the "input type" +of the next command, in order for the result to make sense. +

+

+The intermediate results in a pipe can be observed by putting the +tracing option -tr to each command whose output you +want to see: +

+
+    > gr -tr | l -tr | p
+  
+    Is (This Cheese) Boring
+    this cheese is boring
+    Is (This Cheese) Boring  
+
+

+This facility is useful for test purposes: the pipe above can show +if a grammar is ambiguous, i.e. +contains strings that can be parsed in more than one way. +

+

+Exercise. Extend the Food grammar so that it produces ambiguous +strings, and try out the ambiguity test. +

+ +

Writing and reading files

+

+To save the outputs of GF commands into a file, you can +pipe it to the write_file = wf command, +

+
+    > gr -number=10 | linearize | write_file exx.tmp
+
+

+You can read the file back to GF with the +read_file = rf command, +

+
+    > read_file exx.tmp | parse -lines
+
+

+Notice the flag -lines given to the parsing +command. This flag tells GF to parse each line of +the file separately. Without the flag, the grammar could +not recognize the string in the file, because it is not +a sentence but a sequence of ten sentences. +

+

+Files with examples can be used for regression testing +of grammars. The most systematic way to do this is by +generating treebanks; see here. +

+ +

Visualizing trees

+

+The gibberish code with parentheses returned by the parser does not +look like trees. Why is it called so? From the abstract mathematical +point of view, trees are a data structure that +represents nesting: trees are branching entities, and the branches +are themselves trees. Parentheses give a linear representation of trees, +useful for the computer. But the human eye may prefer to see a visualization; +for this purpose, GF provides the command visualize_tree = vt, to which +parsing (and any other tree-producing command) can be piped: +

+
+    > parse "this delicious cheese is very Italian" | visualize_tree
+
+

+

+ +

+

+This command uses the programs Graphviz and Ghostview, which you +might not have, but which are freely available on the web. +

+

+Alternatively, you can print the tree into a file +e.g. a .png file that +can be be viewed with e.g. an HTML browser and also included in an +HTML document. You can do this +by saving the file grphtmp.dot, which the command vt +produces. Then you can process this file with the dot +program (from the Graphviz package). +

+
+    % dot -Tpng grphtmp.dot > mytree.png
+
+

+ +

System commands

+

+If you don't have Ghostview, or want to view graphs in some other way, +you can call dot and a suitable +viewer (e.g. open in Mac) without leaving GF, by using +a system command: ! followed by a Unix command, +

+
+    > ! dot -Tpng grphtmp.dot > mytree.png
+    > ! open mytree.png
+
+

+Another form of system commands are those that receive arguments from +GF pipes. The escape symbol +is then ?. +

+
+    > generate_trees | ? wc
+
+

+

+Exercise. (Exercise drom 3.3.1 revisited.) +Measure how many trees the grammar FoodEng gives with depths 4 and 5, +respectively. Use the Unix word count command wc to count lines, and +a pipe from a GF command into a Unix command. +

+ +

An Italian concrete syntax

+

+ +

+

+We write the Italian grammar in a straightforward way, by replacing +English words with their dictionary equivalents: +

+
+    concrete FoodIta of Food = {
+  
+      lincat
+        Phrase, Item, Kind, Quality = {s : Str} ;
+  
+      lin
+        Is item quality = {s = item.s ++ "è" ++ quality.s} ;
+        This kind = {s = "questo" ++ kind.s} ;
+        That kind = {s = "quello" ++ kind.s} ;
+        QKind quality kind = {s = kind.s ++ quality.s} ;
+        Wine = {s = "vino"} ;
+        Cheese = {s = "formaggio"} ;
+        Fish = {s = "pesce"} ;
+        Very quality = {s = "molto" ++ quality.s} ;
+        Fresh = {s = "fresco"} ;
+        Warm = {s = "caldo"} ;
+        Italian = {s = "italiano"} ;
+        Expensive = {s = "caro"} ;
+        Delicious = {s = "delizioso"} ;
+        Boring = {s = "noioso"} ;
+    }
+
+

+An alert reader, or one who already knows Italian, may notice one point in +which the change is more substantial than just replacement of words: the order of +a quality and the kind it modifies in +

+
+      QKind quality kind = {s = kind.s ++ quality.s} ;
+
+

+Thus Italian says vino italiano for Italian wine. (Some Italian adjectives +are put before the noun. This distinction can be controlled by parameters, which +are introduced in the fourth chapter.) +

+

+Exercise. Write a concrete syntax of Food for some other language. +You will probably end up with grammatically incorrect linearizations --- but don't +worry about this yet. +

+

+Exercise. If you have written Food for German, Swedish, or some +other language, test with random or exhaustive generation what constructs +come out incorrect, and prepare a list of those ones that cannot be helped +with the currently available fragment of GF. You can return to your list +after having worked out the fourth chapter. +

+ +

Free variation

+

+Sometimes there are alternative ways to define a concrete syntax. +For instance, if we use the Food grammars in a restaurant phrase +book, we may want to accept different words for expressing the quality +"delicious" ---- and different languages can differ in how many +such words they have. Then we don't want to put the distinctions into +the abstract syntax, but into concrete syntaxes. Such semantically +neutral distinctions are known as free variation in linguistics. +

+

+The variants construct of GF expresses free variation. For example, +

+
+    lin Delicious = {s = variants {"delicious" ; "exquisit" ; "tasty"}} ;
+
+

+says that Delicious can be linearized to any of delicious, +exquisit, and tasty. As a consequence, both these words result in the +tree Delicious when parsed. By default, the linearize command +shows only the first variant from each variants list; to see them +all, the option -all can be used: +

+
+    > p "this exquisit wine is delicious" | l -all
+    this delicious wine is delicious
+    this delicious wine is exquisit
+    ...
+
+

+In linguistics, it is well known that free variation is almost +non-existing, if all aspects of expressions are taken into account, including style. +Therefore, free variation should not be used in grammars that are meant as +libraries for other grammars, as in the fifth chapter. However, in a specific +application, free variation is an excellent way to scale up the parser to +variations in user input that make no difference in the semantic +treatment. +

+

+An example that clearly illustrates these points is the +English negation. If we added to the Food grammar the negation +of a quality, we could accept both contracted and uncontracted not: +

+
+    fun IsNot : Item -> Quality -> Phrase ;
+    lin IsNot item qual = 
+      {s = item.s ++ variants {"isn't" ; ["is not"]} ++ qual.s} ;
+
+

+Both forms are likely to occur in user input. Since there is no +corresponding contrast in Italian, we do not want to put the distinction +in the abstract syntax. Yet there is a stylistic difference between +these two forms. In particular, if we are doing generation rather +than parsing, we will want to choose the one or +the other depending on the kind of language we want to generate. +

+

+A limiting case of free variation is an empty variant list +

+
+    variants {}
+
+

+It can be used e.g. if a word lacks a certain inflection form. +

+

+Free variation works for all types in concrete syntax; all terms in +a variants list must be of the same type. +

+

+Exercise. Modify FoodIta in such a way that a quality can +be assigned to an item by using two different word orders, exemplified +by questo vino è delizioso and è delizioso questo vino +(a real variation in Italian), +and that it is impossible to say that something is boring +(a rather contrived example). +

+ +

More application of multilingual grammars

+ +

Multilingual treebanks

+

+ +

+

+A multilingual treebank is a set of trees with their +translations in different languages: +

+
+    > gr -number=2 | tree_bank
+  
+    Is (That Cheese) (Very Boring)
+    quello formaggio è molto noioso
+    that cheese is very boring
+  
+    Is (That Cheese) Fresh
+    quello formaggio è fresco
+    that cheese is fresh
+
+

+There is also an XML format for treebanks and a set of commands +suitable for regression testing; see help tb for more details. +

+ +

Translation session

+

+If translation is what you want to do with a set of grammars, a convenient +way to do it is to open a translation_session = ts. In this session, +you can translate between all the languages that are in scope. +A dot . terminates the translation session. +

+
+    > ts
+  
+    trans> that very warm cheese is boring
+    quello formaggio molto caldo è noioso
+    that very warm cheese is boring
+  
+    trans> questo vino molto italiano è molto delizioso
+    questo vino molto italiano è molto delizioso
+    this very Italian wine is very delicious
+  
+    trans> .
+    >
+
+

+ +

Translation quiz

+

+This is a simple language exercise that can be automatically +generated from a multilingual grammar. The system generates a set of +random sentences, displays them in one language, and checks the user's +answer given in another language. The command translation_quiz = tq +makes this in a subshell of GF. +

+
+    > translation_quiz FoodEng FoodIta
+  
+    Welcome to GF Translation Quiz.
+    The quiz is over when you have done at least 10 examples
+    with at least 75 % success.
+    You can interrupt the quiz by entering a line consisting of a dot ('.').
+  
+    this fish is warm
+    questo pesce è caldo
+    > Yes.
+    Score 1/1
+  
+    this cheese is Italian
+    questo formaggio è noioso
+    > No, not questo formaggio è noioso, but
+    questo formaggio è italiano
+  
+    Score 1/2
+    this fish is expensive
+
+

+You can also generate a list of translation exercises and save it in a +file for later use, by the command translation_list = tl +

+
+    > translation_list -number=25 FoodEng FoodIta | write_file transl.txt
+
+

+The number flag gives the number of sentences generated. +

+ +

Multilingual syntax editing

+

+ +

+

+Any multilingual grammar can be used in the graphical syntax editor, which is +opened by the shell +command gfeditor followed by the names of the grammar files. +Thus +

+
+    % gfeditor FoodEng.gf FoodIta.gf 
+
+

+opens the editor for the two Food grammars. +

+

+The editor supports commands for manipulating an abstract syntax tree. +The process is started by choosing a category from the "New" menu. +Choosing Phrase creates a new tree of type Phrase. A new tree +is in general completely unknown: it consists of a metavariable +?1. However, since the category Phrase in Food has +only one possible constructor, Is, the tree is readily +given the form Is ?1 ?2. Here is what the editor looks like at +this stage: +

+

+ +

+

+Editing goes on by refinements, i.e. choices of constructors from +the menu, until no metavariables remain. Here is a tree resulting from the +current editing session: +

+

+ +

+

+Editing can be continued even when the tree is finished. The user can shift +the focus to some of the subtrees by clicking at it or the corresponding +part of a linearization. In the picture, the focus is on "fish". +Since there are no metavariables, +the menu shows no refinements, but some other possible actions: +

+
    +
  • to change "fish" to "cheese" or "wine" +
  • to delete "fish", i.e. change it to a metavariable +
  • to wrap "fish" in a qualification, i.e. change it to + QKind ? Fish, where the quality can be given in a later refinement +
+ +

+In addition to menu-based editing, the tool supports refinement by parsing, +which is accessible by middle-clicking in the tree or in the linearization field. +

+

+Exercise. Construct the sentence +this very expensive cheese is very very delicious +and its Italian translation by using gfeditor. +

+ +

Context-free grammars and GF

+

+Readers not familar with context-free grammars, also known as BNF grammars, can +skip this section. Those that are familar with them will find here the exact +relation between GF and context-free grammars. We will moreover show how +the BNF format can be used as input to the GF program; it is often more +concise than GF proper, but also more restricted in expressive power. +

+ +

The "cf" grammar format

+

+The grammar FoodEng could be written in a BNF format as follows: +

+
+    Is.        Phrase  ::= Item "is" Quality ;
+    That.      Item    ::= "that" Kind ;
+    This.      Item    ::= "this" Kind ;
+    QKind.     Kind    ::= Quality Kind ;
+    Cheese.    Kind    ::= "cheese" ;
+    Fish.      Kind    ::= "fish" ;
+    Wine.      Kind    ::= "wine" ;
+    Italian.   Quality ::= "Italian" ;
+    Boring.    Quality ::= "boring" ;
+    Delicious. Quality ::= "delicious" ;
+    Expensive. Quality ::= "expensive" ;
+    Fresh.     Quality ::= "fresh" ;
+    Very.      Quality ::= "very" Quality ;
+    Warm.      Quality ::= "warm" ;
+
+

+In this format, each rule is prefixed by a label that gives +the constructor function GF gives in its fun rules. In fact, +each context-free rule is a fusion of a fun and a lin rule: +it states simultaneously that +

+
    +
  • the label is a function from the nonterminal categories + on the right-hand side to the category on the left-hand side; + the first rule gives +
    +    fun Is : Item -> Quality -> Phrase 
    +
    +
  • trees built by the label are linearized in the way indicated + by the right-hand side; + the first rule gives +
    +    lin Is item quality = {s = item.s ++ "is" ++ quality.s}
    +
    +
+ +

+The translation from BNF to GF described above is in fact used in +the GF system to convert BNF grammars into GF. BNF files are recognized +by the file name suffix .cf; thus the grammar above can be +put into a file named food.cf and read into GF by +

+
+    > import food.cf
+
+

+ +

Restrictions of context-free grammars

+

+Even though we managed to write FoodEng in the context-free format, +we cannot do this for GF grammars in general. It is enough to try this +with FoodIta at the same time as FoodEng, +we lose an important aspect of multilinguality: +that the order of constituents is defined only in concrete syntax. +Thus we could not use context-free FoodEng and FoodIta in a multilingual +grammar that supports translation via common abstract syntax: the +qualification function QKind has different types in the two +grammars. +

+

+In general terms, the separation of concrete and abstract syntax allows +three deviations from context-free grammar: +

+
    +
  • permutation: changing the order of constituents +
  • suppression: omitting constituents +
  • reduplication: repeating constituents +
+ +

+The third property is the one that definitely shows that GF is +stronger than context-free: GF can define the copy language +{x x | x <- (a|b)*}, which is known not to be context-free. +The other properties have more to do with the kind of trees that +the grammar can associate with strings: permutation is important +in multilingual grammars, and suppression is exploited in grammars +where trees carry some hidden semantic information (see the sixth chapter +below). +

+

+Of course, context-free grammars are also restricted from the +grammar engineering point of view. They give no support to +modules, functions, and parameters, which are so central +for the productivity of GF. Despite the initial conciseness +of context-free grammars, GF can easily produce grammars where +30 lines of GF code would need hundreds of lines of +context-free grammar code to produce; see exercises +here and here. +

+

+Exercise. GF can also interpret unlabelled BNF grammars, by +creating labels automatically. The right-hand sides of BNF rules +can moreover be disjunctions, e.g. +

+
+    Quality ::= "fresh" | "Italian" | "very" Quality ;
+
+

+Experiment with this format in GF, possibly with a grammar that +you import from some other source, such as a programming language +document. +

+

+Exercise. Define the copy language {x x | x <- (a|b)*} in GF. +

+ +

Modules and files

+

+GF uses suffixes to recognize different file formats. The most +important ones are: +

+
    +
  • Source files: Modulename.gf +
  • Target files: Modulename.gfc +
+ +

+When you import FoodEng.gf, you see the target files being +generated: +

+
+    > i FoodEng.gf
+    - compiling Food.gf...   wrote file Food.gfc 16 msec
+    - compiling FoodEng.gf...   wrote file FoodEng.gfc 20 msec
+
+

+You also see that the GF program does not only read the file +FoodEng.gf, but also all other files that it +depends on --- in this case, Food.gf. +

+

+For each file that is compiled, a .gfc file +is generated. The GFC format (="GF Canonical") is the +"machine code" of GF, which is faster to process than +GF source files. When reading a module, GF decides whether +to use an existing .gfc file or to generate +a new one, by looking at modification times. +

+

+In GF version 3, the gfc format is replaced by the format suffixed +gfo, "GF object". +

+

+Exercise. What happens when you import FoodEng.gf for +a second time? Try this in different situations: +

+
    +
  • Right after importing it the first time (the modules are kept in + the memory of GF and need no reloading). +
  • After issuing the command empty (e), which clears the memory + of GF. +
  • After making a small change in FoodEng.gf, be it only an added space. +
  • After making a change in Food.gf. +
+ + +

Using operations and resource modules

+ +

The golden rule of functional programming

+

+When writing a grammar, you have to type lots of +characters. You have probably +done this by the copy-and-paste method, which is a universally +available way to avoid repeating work. +

+

+However, there is a more elegant way to avoid repeating work than +the copy-and-paste +method. The golden rule of functional programming says that +

+
    +
  • whenever you find yourself programming by copy-and-paste, + write a function instead. +
+ +

+A function separates the shared parts of different computations from the +changing parts, its arguments, or parameters. +In functional programming languages, such as +Haskell, it is possible to share much more +code with functions than in languages such as C and Java, because +of higher-order functions (functions that takes functions as arguments). +

+ +

Operation definitions

+

+GF is a functional programming language, not only in the sense that +the abstract syntax is a system of functions (fun), but also because +functional programming can be used when defining concrete syntax. This is +done by using a new form of judgement, with the keyword oper (for +operation), distinct from fun for the sake of clarity. +Here is a simple example of an operation: +

+
+    oper ss : Str -> {s : Str} = \x -> {s = x} ;
+
+

+The operation can be applied to an argument, and GF will +compute the application into a value. For instance, +

+
+    ss "boy" ===> {s = "boy"}
+
+

+We use the symbol === to indicate how an expression is +computed into a value; this symbol is not a part of GF. +

+

+Thus an oper judgement includes the name of the defined operation, +its type, and an expression defining it. As for the syntax of the defining +expression, notice the lambda abstraction form \x -> t of +the function. It reads: function with variable x and function body +t. Any occurrence of x in t is said to be bound in t. +

+

+For lambda abstraction with multiple arguments, we have the shorthand +

+
+    \x,y -> t   ===  \x -> \y -> t
+
+

+The notation we have used for linearization rules, where +variables are bound on the left-hand side, is actually syntactic +sugar for abstraction: +

+
+    lin f x = t   ===  lin f = \x -> t
+
+

+ +

The ``resource`` module type

+

+Operator definitions can be included in a concrete syntax. +But they are usually not really tied to a particular +set of linearization rules. +They should rather be seen as resources +usable in many concrete syntaxes. +

+

+The resource module type is used to package +oper definitions into reusable resources. Here is +an example, with a handful of operations to manipulate +strings and records. +

+
+    resource StringOper = {
+      oper
+        SS : Type = {s : Str} ;
+        ss : Str -> SS = \x -> {s = x} ;
+        cc : SS -> SS -> SS = \x,y -> ss (x.s ++ y.s) ;
+        prefix : Str -> SS -> SS = \p,x -> ss (p ++ x.s) ;
+    }
+
+

+ +

Opening a resource

+

+Any number of resource modules can be +opened in a concrete syntax, which +makes definitions contained +in the resource usable in the concrete syntax. Here is +an example, where the resource StringOper is +opened in a new version of FoodEng. +

+
+    concrete FoodEng of Food = open StringOper in {
+  
+      lincat
+        S, Item, Kind, Quality = SS ;
+  
+      lin
+        Is item quality = cc item (prefix "is" quality) ;
+        This k = prefix "this" k ;
+        That k = prefix "that" k ;
+        QKind k q = cc k q ;
+        Wine = ss "wine" ;
+        Cheese = ss "cheese" ;
+        Fish = ss "fish" ;
+        Very = prefix "very" ;
+        Fresh = ss "fresh" ;
+        Warm = ss "warm" ;
+        Italian = ss "Italian" ;
+        Expensive = ss "expensive" ;
+        Delicious = ss "delicious" ;
+        Boring = ss "boring" ;
+    }
+
+

+

+Exercise. Use the same string operations to write FoodIta +more concisely. +

+ +

Partial application

+

+ +

+

+GF, like Haskell, permits partial application of +functions. An example of this is the rule +

+
+    lin This k = prefix "this" k ;
+
+

+which can be written more concisely +

+
+    lin This = prefix "this" ;
+
+

+The first form is perhaps more intuitive to write +but, once you get used to partial application, you will appreciate its +conciseness and elegance. The logic of partial application +is known as currying, with a reference to Haskell B. Curry. +The idea is that any n-place function can be seen as a 1-place +function whose value is an n-1 -place function. Thus +

+
+    oper prefix : Str -> SS -> SS ;
+
+

+can be used as a 1-place function that takes a Str into a +function SS -> SS. The expected linearization of This is exactly +a function of such a type, operating on an argument of type Kind +whose linearization is of type SS. Thus we can define the +linearization directly as prefix "this". +

+

+An important part of the art of functional programming is to decide the order +of arguments in a function, so that partial application can be used as much +as possible. For instance, of the operation prefix we know that it +will be typically applied to linearization variables with constant strings. +This is the reason to put the Str argument before the SS argument --- not +the prefixity. A postfix function would have exactly the same order of arguments. +

+

+Exercise. Define an operation infix analogous to prefix, +such that it allows you to write +

+
+    lin Is = infix "is" ;
+
+

+ +

Testing resource modules

+

+To test a resource module independently, you must import it +with the flag -retain, which tells GF to retain oper definitions +in the memory; the usual behaviour is that oper definitions +are just applied to compile linearization rules +(this is called inlining) and then thrown away. +

+
+    > import -retain StringOper.gf
+
+

+The command compute_concrete = cc computes any expression +formed by operations and other GF constructs. For example, +

+
+    > compute_concrete prefix "in" (ss "addition")
+    {
+      s : Str = "in" ++ "addition"
+    }
+
+

+ +

Grammar architecture

+

+ +

+ +

Extending a grammar

+

+The module system of GF makes it possible to write a new module that extends +an old one. The syntax of extension is +shown by the following example. We extend Food into MoreFood by +adding a category of questions and two new functions. +

+
+    abstract Morefood = Food ** {
+      cat
+        Question ;
+      fun
+        QIs : Item -> Quality -> Question ;
+        Pizza : Kind ;
+        
+    }
+
+

+Parallel to the abstract syntax, extensions can +be built for concrete syntaxes: +

+
+    concrete MorefoodEng of Morefood = FoodEng ** {
+      lincat
+        Question = {s : Str} ;
+      lin
+        QIs item quality = {s = "is" ++ item.s ++ quality.s} ;
+        Pizza = {s = "pizza"} ;
+    }
+
+

+The effect of extension is that all of the contents of the extended +and extending module are put together. We also say that the new +module inherits the contents of the old module. +

+

+At the same time as extending a module of the same type, a concrete +syntax module may open resources. Since open takes effect in +the module body and not in the extended module, its logical place +in the module header is after the extend part: +

+
+    concrete MorefoodIta of Morefood = FoodIta ** open StringOper in {
+      lincat
+        Question = SS ;
+      lin
+        QIs item quality = ss (item.s ++ "è" ++ quality.s) ;
+        Pizza = ss "pizza" ;
+    }
+
+

+Resource modules can extend other resource modules, in the +same way as modules of other types can extend modules of the +same type. Thus it is possible to build resource hierarchies. +

+ +

Multiple inheritance

+

+Specialized vocabularies can be represented as small grammars that +only do "one thing" each. For instance, the following are grammars +for fruit and mushrooms +

+
+    abstract Fruit = {
+      cat Fruit ;
+      fun Apple, Peach : Fruit ;
+    }
+  
+    abstract Mushroom = {
+      cat Mushroom ;
+      fun Cep, Agaric : Mushroom ;
+    }
+
+

+They can afterwards be combined into bigger grammars by using +multiple inheritance, i.e. extension of several grammars at the +same time: +

+
+    abstract Foodmarket = Food, Fruit, Mushroom ** {
+      fun 
+        FruitKind    : Fruit    -> Kind ;
+        MushroomKind : Mushroom -> Kind ;
+      }
+
+

+The main advantages with splitting a grammar to modules are +reusability, separate compilation, and division of labour. +Reusability means +that one and the same module can be put into different uses; for instance, +a module with mushroom names might be used in a mycological information system +as well as in a restaurant phrasebook. Separate compilation means that a module +once compiled into .gfc need not be compiled again unless changes have +taken place. +Division of labour means simply that programmers that are experts in +special areas can work on modules belonging to those areas. +

+

+Exercise. Refactor Food by taking apart Wine into a special +Drink module. +

+ +

Visualizing module structure

+

+When you have created all the abstract syntaxes and +one set of concrete syntaxes needed for Foodmarket, +your grammar consists of eight GF modules. To see how their +dependences look like, you can use the command +visualize_graph = vg, +

+
+    > visualize_graph
+
+

+and the graph will pop up in a separate window: +

+

+ +

+

+The graph uses +

+
    +
  • oval boxes for abstract modules +
  • square boxes for concrete modules +
  • black-headed arrows for inheritance +
  • white-headed arrows for the concrete-of-abstract relation +
+ +

+Just as the visualize_tree = vt command, the freely available tools +Ghostview and Graphviz are needed. As an alternative, you can again print +the graph into a .dot file by using the command print_multi = pm: +

+
+    > print_multi -printer=graph | write_file Foodmarket.dot
+    > ! dot -Tpng Foodmarket.dot > Foodmarket.png
+
+

+ +

Summary of GF language features

+ +

Modules

+

+The general form of a module is +

+ Moduletype M Of = (Extends **)? (open Opens in)? Body +
+where Moduletype is one of abstract, concrete, and resource. +

+

+If Moduletype is concrete, the Of-part has the form of A, +where A is the name of an abstract module. Otherwise it is empty. +

+

+The name of the module is given by the identifier M. +

+

+The optional Extends part is a comma-separated +list of module names, which have to be modules of +the same Moduletype. The contents of these modules are inherited by +M. This means that they are both usable in Body and exported by M, +i.e. inherited when M is inherited and available when M is opened. +(Exception: oper and param judgements are not inherited from +concrete modules.) +

+

+The optional Opens part is a comma-separated +list of resource module names. The contents of these +modules are usable in the Body, but they are not exported. +

+

+Opening can be qualified, e.g. +

+
+    concrete C of A = open (P = Prelude) in ...
+
+

+This means that the names from Prelude are only available in the form +P.name. This form of qualifying a name is always possible, and it can +be used to resolve name conflicts, which result when the same name is +declared in more than one module that is in scope. +

+ +

Judgements

+

+The Body part consists of judgements. The judgement form table #secjment +is extended with the following forms: +

+ + + + + + + + + + + + + + + + +
formreadingmodule type
oper h : T = toperation h of type T is defined as tresource, concrete
param P = C1 | ... | Cnparameter type P has constructors C1...Cnresource, concrete
+ +

+

+The param judgement will be explained in the next chapter. +

+

+The type part of an oper judgement can be omitted, if the type can be inferred +by the GF compiler. +

+
+    oper hello = "hello" ++ "world" ;
+
+

+As a rule, type inference works for all terms except lambda abstracts. +

+

+Lambda abstracts are expressions of the form \x -> t, +where x is a variable bound in the expression t, which is the +body of the lambda abstract. The type of the lambda abstract is +A ->B, where A is the type of the variable x and +B the type of the body t. +

+

+For multiple lambda abstractions, there is a shorthand +

+
+    \x,y -> t   ===  \x -> \y -> t
+
+

+For lin judgements, there is the shorthand +

+
+    lin f x = t   ===  lin f = \x -> t
+
+

+ +

Free variation

+

+The variants construct of GF can be used to give a list of +concrete syntax terms, of the same type, in free variation. For example, +

+
+    variants {["does not"] ; "doesn't"}
+
+

+A limiting case is the empty variant list variants {}. +

+ +

The context-free grammar format

+

+The .cf file format is used for context-free grammars, which are +always interpretable as GF grammars. Files of this format consist of +rules of the form +

+ (Label .)? Cat ::= RHS ; +
+where the RHS is a sequence of terminals (quoted strings) and +nonterminals (identifiers). The optional Label gives the abstract +syntax function created. If it is omitted, a function name is generated +automatically. Then it is also possible to have more than one RHS, +separated by |. An empty RHS is interpreted as an empty sequence +of terminals, not as an empty disjunction. +

+

+The Extended BNF format (EBNF) can also be used, in files suffixed .ebnf. +This format does not allow user-written labels. The right-hand-side of a rule +can contain everything that is possible in the .cf format, but also +optional parts (p ?), sequences (p *) and non-empty sequences (p +). +For example, the phrases in FoodEng could be recognized with the following +EBNF grammar: +

+
+  Phrase  ::= 
+    ("this" | "that") Quality* ("wine" | "cheese" | "fish") "is" Quality ;
+  Quality ::= 
+    ("very"* ("fresh" | "warm" | "boring" | "Italian" | "expensive")) ;
+
+

+ +

Character encoding

+

+The default encoding is iso-latin-1. UTF-8 can be set by the flag coding=utf8 +in the grammar. The resource grammar libraries are in iso-latin-1, except Russian +and Arabic, which are in UTF-8. The resources may be changed to UTF-8 in future. +Letters in identifiers must currently be iso-latin-1. +

+ +

Grammars with parameters

+

+ +

+

+In this chapter, we will introduce the techniques needed for +describing the inflection of words, as well as the rules by +which correct word forms are selected in syntactic combinations. +These techniques are already needed in a very slight extension +of the Food grammar of the previous chapter. While explaining +how the linguistic problems are solved for English and Italian, +we also cover all the language constructs GF has for +defining concrete syntax. +

+

+It is in principle possible to skip this chapter and go directly +to the next, since the use of the GF Resource Grammar library +makes it unnecessary to use any more constructs of GF than we +have already covered: parameters could be left to library implementors. +

+ +

The problem: words have to be inflected

+

+Suppose we want to say, with the vocabulary included in +Food.gf, things like +

+these Italian wines are delicious +
+The new grammatical facility we need are the plural forms +of nouns and verbs (wines, are), as opposed to their +singular forms. +

+

+The introduction of plural forms requires two things: +

+
    +
  • the inflection of nouns and verbs in singular and plural +
  • the agreement of the verb to subject: + the verb must have the same number as the subject +
+ +

+Different languages have different types of inflection and agreement. +For instance, Italian has also agreement in gender (masculine vs. feminine). +In a multilingual grammar, +we want to express such differences between languages in the +concrete syntax while ignoring them in the abstract syntax. +

+

+To be able to do all this, we need one new judgement form +and some new expression forms. +We also need to generalize linearization types +from strings to more complex types. +

+

+Exercise. Make a list of the possible forms that nouns, +adjectives, and verbs can have in some languages that you know. +

+ +

Parameters and tables

+

+We define the parameter type of number in English by +using a new form of judgement: +

+
+    param Number = Sg | Pl ;
+
+

+This judgement defines the parameter type Number by listing +its two constructors, Sg and Pl (common shorthands for +singular and plural). +

+

+To state that Kind expressions in English have a linearization +depending on number, we replace the linearization type {s : Str} +with a type where the s field is a table depending on number: +

+
+    lincat Kind = {s : Number => Str} ;
+
+

+The table type Number => Str is in many respects similar to +a function type (Number -> Str). The main difference is that the +argument type of a table type must always be a parameter type. This means +that the argument-value pairs can be listed in a finite table. The following +example shows such a table: +

+
+    lin Cheese = {
+      s = table {
+        Sg => "cheese" ;
+        Pl => "cheeses"
+      }
+    } ;
+
+

+The table consists of branches, where a pattern on the +left of the arrow => is assigned a value on the right. +

+

+The application of a table to a parameter is done by the selection +operator !, which is computed by pattern matching: it returns +the value from the first branch whose pattern matches the +selection argument. For instance, +

+
+     table {Sg => "cheese" ; Pl => "cheeses"} ! Pl 
+     ===> "cheeses"
+
+

+As syntactic sugar for table selections, we can define the +case expressions, which are common in functional programming and also +handy to use in GF. +

+
+    case e of {...} ===  table {...} ! e
+
+

+

+A parameter type can have any number of constructors, and these can +also take arguments from other parameter types. For instance, an accurate +type system for English verbs (except be) is +

+
+    param VerbForm = VPresent Number | VPast | VPastPart | VPresPart ;
+
+

+This system expresses accurately the fact that only the present tense has +number variation. (Agreement also requires variation in person, but +this can be defined in syntax rules, by picking the singular form for third person +singular subjects and the plural forms for all others). As an example of +a table, here are the forms of the verb drink: +

+
+    table {
+      VPresent Sg => "drinks" ;
+      VPresent Pl => "drink" ;
+      VPast       => "drank" ;
+      VPastPart   => "drunk" ;
+      VPresPart   => "drinking"
+      }
+
+

+

+Exercise. In an earlier exercise (previous section), +you made a list of the possible +forms that nouns, adjectives, and verbs can have in some languages that +you know. Now take some of the results and implement them by +using parameter type definitions and tables. Write them into a resource +module, which you can test by using the command compute_concrete. +

+ +

Inflection tables and paradigms

+

+All English common nouns are inflected for number, most of them in the +same way: the plural form is obtained from the singular by adding the +ending s. This rule is an example of +a paradigm --- a formula telling how a class of words is inflected. +

+

+From the GF point of view, a paradigm is a function that takes +a lemma --- also known as a dictionary form or a citation form --- and +returns an inflection +table of desired type. Paradigms are not functions in the sense of the +fun judgements of abstract syntax (which operate on trees and not +on strings), but operations defined in oper judgements. +The following operation defines the regular noun paradigm of English: +

+
+    oper regNoun : Str -> {s : Number => Str} = \dog -> {
+      s = table {
+        Sg => dog ;
+        Pl => dog + "s"
+        }
+      } ;
+
+

+The gluing operator + tells that +the string held in the variable dog and the ending "s" +are written together to form one token. Thus, for instance, +

+
+    (regNoun "cheese").s ! Pl  ===> "cheese" + "s"  ===>  "cheeses"
+
+

+A more complex example are regular verbs: +

+
+    oper regVerb : Str -> {s : VerbForm => Str} = \talk -> {
+      s = table {
+        VPresent Sg => talk + "s" ;
+        VPresent Pl => talk ;
+        VPresPart   => talk + "ing" ;
+        _           => talk + "ed"
+        }
+      } ;
+
+

+Notice how a catch-all case for the past tense and the past participle +is expressed by using a wild card pattern _. Here again, pattern matching +tries all patterns in order until it finds a matching pattern; +and it is the wild card that is the first match for both VPast and +VPastPart. +

+

+Exercise. Identify cases in which the regNoun paradigm does not +apply in English, and implement some alternative paradigms. +

+

+Exercise. Implement some regular paradigms for other languages you have +considered in earlier exercises. +

+ +

Using parameters in concrete syntax

+

+We can now enrich the concrete syntax definitions to +comprise morphology. This will permit a more radical +variation between languages (e.g. English and Italian) +than just the use of different words. In general, +parameters and linearization types are different in +different languages --- but this does not prevent using a +the common abstract syntax. +

+

+We consider a grammar Foods, which is similar to +Food, with the addition two rules for forming plural items: +

+
+    fun These, Those : Kind -> Item ;
+
+

+We also add a noun which in Italian has the feminine case; all nouns in +Food were carefully chosen to be masculine! +

+
+    fun Pizza : Kind ;
+
+

+This noun will force us to deal with gender in the Italian grammar, +which is what we need for the grammar to scale up for larger applications. +

+ +

Agreement

+

+In the English Foods grammar, we need just one type of parameters: +Number as defined above. The phrase-forming rule +

+
+    fun Is : Item -> Quality -> Phrase ;
+
+

+is affected by the number because of subject-verb agreement. +In English, agreement says that the verb of a sentence +must be inflected in the number of the subject. Thus we will linearize +

+
+    Is (This Pizza) Warm   ===>  "this pizza is warm"
+    Is (These Pizza) Warm  ===>  "these pizzas are warm"
+
+

+Here it is the copula, i.e. the verb be that is affected. We define +the copula as the operation +

+
+    oper copula : Number -> Str = \n -> 
+      case n of {
+        Sg => "is" ;
+        Pl => "are"
+        } ;
+
+

+We don't need to inflect the copula for person and tense in this grammar. +

+

+The form of the copula in a sentence depends on the +subject of the sentence, i.e. the item +that is qualified. This means that an Item must have such a number to provide. +The obvious way to guarantee this is by including a number field in +the linearization type: +

+
+    lincat Item = {s : Str ; n : Number} ;
+
+

+Now we can write precisely the Is rule that expresses agreement: +

+
+    lin Is item qual = {s = item.s ++ copula item.n ++ qual.s} ;
+
+

+The copula receives the number that it needs from the subject item. +

+ +

Determiners

+

+Let us turn to Item subjects and see how they receive their +numbers. The two rules +

+
+    fun This, These : Kind -> Item ;
+
+

+form Items from Kinds by adding determiners, either +this or these. The determiners +require different numbers of their Kind arguments: This +requires the singular (this pizza) and These the plural +(these pizzas). The Kind is the same in both cases: Pizza. +Thus a Kind must have both singular and plural forms. +The obvious way to express this is by using a table: +

+
+    lincat Kind = {s : Number => Str} ;
+
+

+The linearization rules for This and These can now be written +

+
+    lin This kind = {
+      s = "this" ++ kind.s ! Sg ; 
+      n = Sg
+    } ; 
+  
+    lin These kind = {
+      s = "these" ++ kind.s ! Pl ; 
+      n = Pl
+    } ; 
+
+

+The grammatical relation between the determiner and the noun is similar to +agreement, but due to some differences into which we don't go here +it is often called government. +

+

+Since the same pattern for determination is used four times in +the FoodsEng grammar, we codify it as an operation, +

+
+    oper det : 
+      Str -> Number -> {s : Number => Str} -> {s : Str ; n : Number} = 
+        \det,n,kind -> {
+        s = det ++ kind.s ! n ; 
+        n = n
+      } ; 
+
+

+Now we can write, for instance, +

+
+    lin This  = det Sg "this" ;
+    lin These = det Pl "these" ;
+
+

+Notice the order of arguments that permits partial +application (here). +

+

+In a more lexicalized grammar, determiners would be made into a +category of their own and given an inherent number: +

+
+    lincat Det = {s : Str ; n : Number} ;
+    fun Det : Det -> Kind -> Item ;
+    lin Det det kind = {
+        s = det.s ++ kind.s ! det.n ; 
+        n = det.n
+      } ; 
+
+

+Linguistically motivated grammars, such as the GF resource grammars, +usually favour lexicalized treatments of words; see here below. +Notice that the fields of the record in Det are precisely the two +arguments needed in the det operation. +

+ +

Parametric vs. inherent features

+

+Kinds, as in general common nouns in English, have both singular +and plural forms; what form is chosen is determined by the construction +in which the noun is used. We say that the number is a +parametric feature of nouns. In GF, parametric features +appear as argument types of tables in linearization types. +

+
+    lincat Kind = {s : Number => Str} ;
+
+

+Items, as in general noun phrases in English, don't +have variation in number. The number is instead an inherent feature, +which the noun phrase passes to the verb. In GF, inherent features +appear as record fields in linearization types. +

+
+    lincat Item = {s : Str ; n : Number} ;
+
+

+A category can have both parametric and inherent features. As we will see +in the Italian Foods grammar, nouns have parametric number and +inherent gender: +

+
+    lincat Kind = {s : Number => Str ; g : Gender} ;
+
+

+Nothing prevents the same parameter type from appearing both +as parametric and inherent feature, or the appearance of several inherent +features of the same type, etc. Determining the linearization types +of categories is one of the most crucial steps in the design of a GF +grammar. These two conditions must be in balance: +

+
    +
  • existence: what forms are possible to build by morphological and + other means? +
  • need: what features are expected via agreement or government? +
+ +

+Grammar books and dictionaries give good advice on existence; for instance, +an Italian dictionary has entries such as +

+uomo, pl. uomini, n.m. "man" +
+which tells that uomo is a masculine noun with the plural form uomini. +From this alone, or with a couple more examples, we can generalize to the type +for all nouns in Italian: they have both singular and plural forms and thus +a parametric number, and they have an inherent gender. +

+

+The distinction between parametric and inherent features can be stated in +object-oriented programming terms: a linearization type is like a class, +which has a method for linearization and also some attributes. +In this class, the parametric features appear as arguments to the +linearization method, whereas the inherent features appear as attributes. +

+

+For words, inherent features are usually given ad hoc as lexical information. +For combinations, they are typically inherited from some part of the construction. +For instance, qualified noun constructs in Italian inherit their gender from noun part +(called the head of the construction in linguistics): +

+
+    lin QKind qual kind = 
+      let gen = kind.g in {
+        s = table {n => kind.s ! n ++ qual.s ! gen ! n} ;
+        g = gen
+        } ;
+
+

+This rule uses a local definition (also known as a let expression) to +avoid computing kind.g twice, and also to express the linguistic +generalization that it is the same gender that is both passed to +the adjective and inherited by the construct. +The parametric number feature is in this rule passed to both the noun and +the adjective. In the table, a variable pattern is used to match +any possible number. Variables introduced in patterns are in scope in +the right-hand sides of corresponding branches. Again, it is good to +use a variable to express the linguistic generalization that the number +is passed to the parts, rather than expand the table into Sg and Pl +branches. +

+

+Sometimes the puzzle of making agreement and government work in a grammar has +several solutions. For instance, precedence in programming languages can +be equivalently described by a parametric or an inherent feature +(see here below). +

+

+In natural language applications that use the resource grammar library, +all parameters are hidden from the user, who thereby does not need to bother +about them. The only thing that she has to think about is what linguistic +categories are given as linearization types to each semantic category. +

+

+For instance, the GF resource grammar library has a category NP of +noun phrases, AP of adjectival phrases, and Cl of sentence-like clauses. +In the implementation of Foods here, we will define +

+
+    lincat Phrase = Cl ; Item = NP ; Quality = AP ;
+
+

+To express that an item has a quality, we will use a resource function +

+
+    mkCl : NP -> AP -> Cl ;
+
+

+in the linearization rule: +

+
+    lin Is = mkCl ;
+
+

+In this way, we have no need to think about parameters and agreement. +the fifth chapter will show a complete implementation of Foods by the +resource grammar, port it to many new languages, and extend it with +many new constructs. +

+ +

An English concrete syntax for Foods with parameters

+

+We repeat some of the rules above by showing the entire +module FoodsEng, equipped with parameters. The parameters and +operations are, for the sake of brevity, included in the same module +and not in a separate resource. However, some string operations +from the library Prelude are used. +

+
+    --# -path=.:prelude
+  
+    concrete FoodsEng of Foods = open Prelude in {
+  
+    lincat
+      S, Quality = SS ; 
+      Kind = {s : Number => Str} ; 
+      Item = {s : Str ; n : Number} ; 
+  
+    lin
+      Is item quality = ss (item.s ++ copula item.n ++ quality.s) ;
+      This  = det Sg "this" ;
+      That  = det Sg "that" ;
+      These = det Pl "these" ;
+      Those = det Pl "those" ;
+      QKind quality kind = {s = table {n => quality.s ++ kind.s ! n}} ;
+      Wine = regNoun "wine" ;
+      Cheese = regNoun "cheese" ;
+      Fish = noun "fish" "fish" ;
+      Pizza = regNoun "pizza" ;
+      Very = prefixSS "very" ;
+      Fresh = ss "fresh" ;
+      Warm = ss "warm" ;
+      Italian = ss "Italian" ;
+      Expensive = ss "expensive" ;
+      Delicious = ss "delicious" ;
+      Boring = ss "boring" ;
+  
+    param
+      Number = Sg | Pl ;
+  
+    oper
+      det : Number -> Str -> {s : Number => Str} -> {s : Str ; n : Number} = 
+        \n,d,cn -> {
+          s = d ++ cn.s ! n ;
+          n = n
+        } ;
+      noun : Str -> Str -> {s : Number => Str} = 
+        \man,men -> {s = table {
+          Sg => man ;
+          Pl => men 
+          }
+        } ;
+      regNoun : Str -> {s : Number => Str} = 
+        \car -> noun car (car + "s") ;
+      copula : Number -> Str = 
+        \n -> case n of {
+          Sg => "is" ;
+          Pl => "are"
+          } ;
+    }    
+
+

+To find the Prelude library --- or in general, +GF files located in other directories, a path directive is needed +either on the command line or as the first line of +the topmost file compiled. +The paths in the path list are separated by colons (:), and every item +is interpreted primarily relative to the current directory and, secondarily, +to the value of GF_LIB_PATH (GF library path). Hence it is a +good idea to make GF_LIB_PATH to point into your GF/lib/ whenever +you start working in GF. For instance, in the Bash shell this is done by +

+
+    % export GF_LIB_PATH=<the location of GF/lib in your file system>
+
+

+ +

More on inflection paradigms

+

+ +

+

+Let us try to extend the English noun paradigms so that we can +deal with all nouns, not just the regular ones. The goal is to +provide a morphology module that is maximally easy to use when +words are added to the lexicon. In fact, we can think of a +division of labour where a linguistically trained grammarian +writes a morphology and hands it over to the lexicon writer +who knows much less about the rules of inflection. +

+

+In passing, we will introduce some new GF constructs: local definitions, +regular expression patterns, and operation overloading. +

+ +

Worst-case functions

+

+To start with, it is useful to perform data abstraction from the type +of nouns by writing a constructor operation, a worst-case function: +

+
+    oper mkNoun : Str -> Str -> Noun = \x,y -> {
+      s = table {
+        Sg => x ;
+        Pl => y
+        }
+      } ;
+
+

+This presupposes that we have defined +

+
+    oper Noun : Type = {s : Number => Str} ;
+
+

+Using mkNoun, we can define +

+
+    lin Mouse = mkNoun "mouse" "mice" ;
+
+

+and +

+
+    oper regNoun : Str -> Noun = \x -> mkNoun x (x + "s") ;
+
+

+instead of writing the inflection tables explicitly. +

+

+Nouns like mouse-mice, are so irregular that +it hardly makes sense to see them as instances of a +paradigm that forms the plural from the singular form. +But in general, as we will see, there can be different +regular patterns in a language. +

+

+The grammar engineering advantage of worst-case functions is that +the author of the resource module may change the definitions of +Noun and mkNoun, and still retain the +interface (i.e. the system of type signatures) that makes it +correct to use these functions in concrete modules. In programming +terms, Noun is then treated as an abstract datatype: +its definition is not available, but only an indirect way of constructing +its objects. +

+

+A case where a change of the Noun type could +actually happen is if we introduces case (nominative or +genitive) in the noun inflection: +

+
+    param Case = Nom | Gen ;
+  
+    oper Noun : Type = {s : Number => Case => Str} ;
+
+

+Now we have to redefine the worst-case function +

+
+    oper mkNoun : Str -> Str -> Noun = \x,y -> {
+      s = table {
+        Sg => table {
+          Nom => x ;
+          Gen => x + "'s"
+          } ;
+        Pl => table {
+          Nom => y ;
+          Gen => y + case last y of {
+            "s" => "'" ;
+            _   => "'s"
+          }
+        }
+      } ;
+
+

+But up from this level, we can retain the old definitions +

+
+    lin Mouse = mkNoun "mouse" "mice" ;
+    oper regNoun : Str -> Noun = \x -> mkNoun x (x + "s") ;
+
+

+which will just compute to different values now. +

+

+In the last definition of mkNoun, we used a case expression +on the last character of the plural form to decide if the genitive +should be formed with an ' (as in dogs-dogs') or with +'s (as in mice-mice's). The expression last y +uses the Prelude operation +

+
+    last : Str -> Str ;
+
+

+The case expression uses pattern matching over strings, which +is supported in GF, alongside with pattern matching over +parameters. +

+ +

Intelligent paradigms

+

+Between the completely regular dog-dogs and the completely +irregular mouse-mice, there are some +predictable variations: +

+
    +
  • nouns ending with an y: fly-flies, except if + a vowel precedes the y: boy-boys +
  • nouns ending with s, ch, and a number of + other endings: bus-buses, leech-leeches +
+ +

+One way to deal with them would be to provide alternative paradigms: +

+
+    noun_y : Str -> Noun = \fly -> mkNoun fly (init fly + "ies") ;  
+    noun_s : Str -> Noun = \bus -> mkNoun bus (bus + "es") ;
+
+

+The Prelude function init drops the last character of a token. +But this solution has some drawbacks: +

+
    +
  • it can be difficult to select the correct paradigm +
  • it can be difficult to remember the names of the different paradigms +
+ +

+To help the lexicon builder in this task, the morphology programmer +can put some intelligence in the regular noun paradigm. The easiest +way to express this in GF is by the use of regular expression patterns: +

+
+    regNoun : Str -> Noun = \w -> 
+      let 
+        ws : Str = case w of {
+          _ + ("a" | "e" | "i" | "o") + "o" => w + "s" ;  -- bamboo
+          _ + ("s" | "x" | "sh" | "o")      => w + "es" ; -- bus, hero
+          _ + "z"                           => w + "zes" ;-- quiz 
+          _ + ("a" | "e" | "o" | "u") + "y" => w + "s" ;  -- boy
+          x + "y"                           => x + "ies" ;-- fly
+          _                                 => w + "s"    -- car
+          } 
+      in 
+      mkNoun w ws
+
+

+In this definition, we have used a local definition just in order to +structure the code, even though there is no multiple evaluation to eliminate. +In the case expression itself, we have used +

+
    +
  • disjunctive patterns P | Q +
  • concatenation patterns P + Q +
+ +

+The patterns are ordered in such a way that, for instance, +the suffix "oo" prevents bamboo from matching the suffix +"o". +

+

+Exercise. The same rules that form plural nouns in English also +apply in the formation of third-person singular verbs. +Write a regular verb paradigm that uses this idea, but first +rewrite regNoun so that the analysis needed to build s-forms +is factored out as a separate oper, which is shared with +regVerb. +

+

+Exercise. Extend the verb paradigms to cover all verb forms +in English, with special care taken of variations with the suffix +ed (e.g. try-tried, use-used). +

+

+Exercise. Implement the German Umlaut operation on word stems. +The operation changes the vowel of the stressed stem syllable as follows: +a to ä, au to äu, o to ö, and u to ü. You +can assume that the operation only takes syllables as arguments. Test the +operation to see whether it correctly changes Arzt to Ärzt, +Baum to Bäum, Topf to Töpf, and Kuh to Küh. +

+ +

Function types with variables

+

+In the sixth chapter, we will introduce dependent function types, where +the value type depends on the argument. For this end, we need a notation +that binds a variable to the argument type, as in +

+
+    switchOff : (k : Kind) -> Action k
+
+

+Function types without +variables are actually a shorthand notation: writing +

+
+    PredVP : NP -> VP -> S
+
+

+is shorthand for +

+
+    PredVP : (x : NP) -> (y : VP) -> S
+
+

+or any other naming of the variables. Actually the use of variables +sometimes shortens the code, since they can share a type: +

+
+    octuple : (x,y,z,u,v,w,s,t : Str) -> Str
+
+

+If a bound variable is not used, it can here, as elsewhere in GF, be replaced by +a wildcard: +

+
+    octuple : (_,_,_,_,_,_,_,_ : Str) -> Str
+
+

+A good practice for functions with many arguments of the same type +is to indicate the number of arguments: +

+
+    octuple : (x1,_,_,_,_,_,_,x8 : Str) -> Str
+
+

+One can also use heuristic variable names to document what +information each argument is expected to provide. +This is very handy in the types of inflection paradigms: +

+
+    mkNoun : (mouse,mice : Str) -> Noun
+
+

+ +

Separating operation types and definitions

+

+In grammars intended as libraries, it is useful to separate oparation +definitions from their type signatures. The user is only interested +in the type, whereas the definition is kept for the implementor and +the maintainer. This is possible by using separate oper fragments +for the two parts: +

+
+    oper regNoun : Str -> Noun ;
+    oper regNoun s = mkNoun s (s + "s") ;
+
+

+The type checker combines the two into one oper judgement to see +if the definition matches the type. Notice that, in this syntax, it +is moreover possible to bind the argument variables on the left hand side +instead of using lambda abstration. +

+

+In the library module, the type signatures are typically placed in +the beginning and the definitions in the end. A more radical separation +can be achieved by using the interface and instance module types +(see here): the type signatures are placed in the interface +and the definitions in the instance. +

+ +

Overloading of operations

+

+Large libraries, such as the GF Resource Grammar Library, may define +hundreds of names. This can be unpractical +for both the library author and the user: the author has to invent longer +and longer names which are not always intuitive, +and the author has to learn or at least be able to find all these names. +A solution to this problem, adopted by languages such as C++, +is overloading: one and the same name can be used for several functions. +When such a name is used, the +compiler performs overload resolution to find out which of +the possible functions is meant. Overload resolution is based on +the types of the functions: all functions that +have the same name must have different types. +

+

+In C++, functions with the same name can be scattered everywhere in the program. +In GF, they must be grouped together in overload groups. Here is an example +of an overload group, giving the different ways to define nouns in English: +

+
+    oper mkN : overload {
+      mkN : (dog : Str) -> Noun ;         -- regular nouns
+      mkN : (mouse,mice : Str) -> Noun ;  -- irregular nouns
+    }
+
+

+Intuitively, the function comes very close to the way in which +regular and irregular words are given in most dictionaries. If the +word is regular, just one form is needed. If it is irregular, +more forms are given. There is no need to use explicit paradigm +names. +

+

+The mkN example gives only the possible types of the overloaded +operation. Their definitions can be given separately, possibly in another module. +Here is a definition of the above overload group: +

+
+    oper mkN = overload {
+      mkN : (dog : Str) -> Noun = regNoun ;
+      mkN : (mouse,mice : Str) -> Noun = mkNoun ;
+    }
+
+

+Notice that the types of the branches must be repeated so that they can be +associated with proper definitions; the order of the branches has no +significance. +

+

+Exercise. Design a system of English verb paradigms presented by +an overload group. +

+ +

Morphological analysis and morphology quiz

+

+Even though morphology is in GF +mostly used as an auxiliary for syntax, it +can also be useful on its own right. The command morpho_analyse = ma +can be used to read a text and return for each word the analyses that +it has in the current concrete syntax. +

+
+    > read_file bible.txt | morpho_analyse
+
+

+In the same way as translation exercises, morphological exercises can +be generated, by the command morpho_quiz = mq. Usually, +the category is then set to some lexical category. For instance, +French irregular verbs in the resource grammar library can be trained as +follows: +

+
+    % gf -path=alltenses:prelude $GF_LIB_PATH/alltenses/IrregFre.gfc
+  
+    > morpho_quiz -cat=V
+  
+    Welcome to GF Morphology Quiz.
+    ...
+  
+    réapparaître : VFin VCondit  Pl  P2
+    réapparaitriez
+    > No, not réapparaitriez, but
+    réapparaîtriez
+    Score 0/1
+
+

+Just like translation exercises, a list of morphological exercises can be generated +off-line and saved in a +file for later use, by the command morpho_list = ml +

+
+    > morpho_list -number=25 -cat=V | write_file exx.txt
+
+

+The number flag gives the number of exercises generated. +

+ +

The Italian Foods grammar

+

+ +

+

+We conclude the parametrization of the Food grammar by presenting an +Italian variant, now complete with parameters, inflection, and +agreement. +

+

+The header part is similar to English: +

+
+  --# -path=.:prelude
+  
+  concrete FoodsIta of Foods = open Prelude in {
+
+

+Parameters include not only number but also gender. +

+
+    param
+      Number = Sg | Pl ;
+      Gender = Masc | Fem ;
+
+

+Qualities are inflected for gender and number, whereas kinds +have a parametric number (as in English) and an inherent gender. +Items have an inherent number (as in English) but also gender. +

+
+    lincat
+      Phr = SS ; 
+      Quality = {s : Gender => Number => Str} ; 
+      Kind = {s : Number => Str ; g : Gender} ; 
+      Item = {s : Str ; g : Gender ; n : Number} ; 
+
+

+A Quality is expressed by an adjective, which in Italian has one form for each +gender-number combination. +

+
+    oper
+      adjective : (_,_,_,_ : Str) -> {s : Gender => Number => Str} = 
+        \nero,nera,neri,nere -> {
+          s = table {
+            Masc => table {
+              Sg => nero ;
+              Pl => neri
+              } ; 
+            Fem => table {
+              Sg => nera ;
+              Pl => nere
+              }
+            }
+        } ;
+
+

+The very common case of regular adjectives works by adding +endings to the stem. +

+
+      regAdj : Str -> {s : Gender => Number => Str} = \nero ->
+        let ner = init nero 
+        in adjective nero (ner + "a") (ner + "i") (ner + "e") ;
+
+

+

+For noun inflection, there are several paradigms; since only two forms +are ever needed, we will just give them explicitly (the resource grammar +library also has a paradigm that takes the singular form and infers the +plural and the gender from it). +

+
+      noun : Str -> Str -> Gender -> {s : Number => Str ; g : Gender} = 
+        \vino,vini,g -> {
+          s = table {
+            Sg => vino ;
+            Pl => vini
+            } ;
+          g = g
+        } ;
+
+

+As in FoodEng, we need only number variation for the copula. +

+
+      copula : Number -> Str = 
+        \n -> case n of {
+          Sg => "è" ;
+          Pl => "sono"
+          } ;
+
+

+Determination is more complex than in English, because of gender: +it uses separate determiner forms for the two genders, and selects +one of them as function of the noun determined. +

+
+      det : Number -> Str -> Str -> {s : Number => Str ; g : Gender} -> 
+          {s : Str ; g : Gender ; n : Number} = 
+        \n,m,f,cn -> {
+          s = case cn.g of {Masc => m ; Fem => f} ++ cn.s ! n ;
+          g = cn.g ;
+          n = n
+        } ;
+
+

+Here is, finally, the complete set of linearization rules. +

+
+    lin
+      Is item quality = 
+        ss (item.s ++ copula item.n ++ quality.s ! item.g ! item.n) ;
+      This  = det Sg "questo" "questa" ;
+      That  = det Sg "quello" "quella" ;
+      These = det Pl "questi" "queste" ;
+      Those = det Pl "quelli" "quelle" ;
+      QKind quality kind = {
+        s = \\n => kind.s ! n ++ quality.s ! kind.g ! n ;
+        g = kind.g
+        } ;
+      Wine = noun "vino" "vini" Masc ;
+      Cheese = noun "formaggio" "formaggi" Masc ;
+      Fish = noun "pesce" "pesci" Masc ;
+      Pizza = noun "pizza" "pizze" Fem ;
+      Very qual = {s = \\g,n => "molto" ++ qual.s ! g ! n} ;
+      Fresh = adjective "fresco" "fresca" "freschi" "fresche" ;
+      Warm = regAdj "caldo" ;
+      Italian = regAdj "italiano" ;
+      Expensive = regAdj "caro" ;
+      Delicious = regAdj "delizioso" ;
+      Boring = regAdj "noioso" ;
+    }
+
+

+

+Exercise. Experiment with multilingual generation and translation in the +Foods grammars. +

+

+Exercise. Add items, qualities, and determiners to the grammar, and try to get +their inflection and inherent features right. +

+

+Exercise. Write a concrete syntax of Food for a language of your choice, +now aiming for complete grammatical correctness by the use of parameters. +

+

+Exercise. Measure the size of the context-free grammar corresponding to +FoodsIta. You can do this by printing the grammar in the context-free format +(print_grammar -printer=cfg) and counting the lines. +

+ +

Discontinuous constituents

+

+A linearization type may contain more strings than one. +An example of where this is useful are English particle +verbs, such as switch off. The linearization of +a sentence may place the object between the verb and the particle: +he switched it off. +

+

+The following judgement defines transitive verbs as +discontinuous constituents, i.e. as having a linearization +type with two strings and not just one. +

+
+    lincat TV = {s : Number => Str ; part : Str} ;
+
+

+In the abstract syntax, we can now have a rule that combines a subject and an +object item with a transitive verb to form a sentence: +

+
+    fun AppTV : Item -> TV -> Item -> Phrase ;
+
+

+The linearization rule places the object between the two parts of the verb: +

+
+    lin AppTV subj tv obj = 
+      {s = subj.s ++ tv.s ! subj.n ++ obj.s ++ tv.part} ;
+
+

+There is no restriction in the number of discontinuous constituents +(or other fields) a lincat may contain. The only condition is that +the fields must be built from records, tables, +parameters, and Str, but not functions. +

+

+Notice that the parsing and linearization commands only give accurate +results for categories whose linearization type has a unique Str +valued field labelled s. Therefore, discontinuous constituents +are not a good idea in top-level categories accessed by the users +of a grammar application. +

+

+Exercise. Define the language a^n b^n c^n in GF, i.e. +any number of a's followed by the same number of b's and +the same number of c's. This language is not context-free, +but can be defined in GF by using discontinuous constituents. +

+ +

Strings at compile time vs. run time

+

+A common difficulty in GF are the conditions under which tokens +can be created. Tokens are created in the following ways: +

+
    +
  • quoted string: "foo" +
  • gluing : t + s +
  • predefined operations init, tail, tk, dp +
  • pattern matching over strings +
+ +

+The general principle is that +tokens must be known at compile time. This means that the above operations +may not have run-time variables in their arguments. Run-time variables, in +turn, are the variables that stand for function arguments in linearization rules. +

+

+Hence it is not legal to write +

+
+    cat Noun ;
+    fun Plural : Noun -> Noun ;
+    lin Plural n = {s = n.s + "s"} ;
+
+

+because n is a run-time variable. Also +

+
+    lin Plural n = {s = (regNoun n).s ! Pl} ; 
+
+

+is incorrect with regNoun as defined here, because the run-time +variable is eventually sent to string pattern matching and gluing. +

+

+Writing tokens together without a space is an often-wanted behaviour, for instance, +with punctuation marks. Thus one might try to write +

+
+    lin Question p = {s = p + "?"} ;
+
+

+which is incorrect. The way to go is to use an unlexer that creates correct spacing +after linearization. Correspondingly, a lexer that e.g. analyses "warm?" into +to tokens is needed before parsing. This can be done by using flags: +

+
+    flags lexer=text ; unlexer=text ;
+
+

+works in the desired way for English text. More on lexers and unlexers will be +told here. +

+ +

Summary of GF language features

+ +

Parameter and table types

+

+A judgement of the form +

+ param P = C1 X1 | ... | Cn Xn +
+defines a parameter type P with constructors C1 ... Cn. +Each constructor has a context X, which is a (possibly empty) +sequence of parameter types. A parameter value is an application +of a constructor to a sequence of parameter values from each type in +its context. +

+

+In addition to types defined in param judgements, also +records of parameter types are parameter types. Their values are records +of corresponding field values. +

+

+Moreover, the type Ints n is a parameter type for any positive +integer n, and its values are 0, ..., n-1. +

+

+A table type P => T must have a parameter type P as +its argument type. The normal form of an object of this type is a table +

+ table { V1 => t1 ; ... ; Vm => tm } +
+which has a branch for every parameter value Vi of type P. +A table can be given in many other ways by using pattern matching. +

+

+Tables with only one branch are a common special case. +GF provides syntactic sugar for writing one-branch tables concisely: +

+
+    \\P,...,Q => t  ===  table {P => ... table {Q => t} ...}
+
+

+ +

Pattern matching

+

+ +

+

+We will list all forms of patterns that can be used in table branches. +the following are available for any parameter types, as well +as for the types Int and Str +

+
    +
  • a constructor pattern C P1 ... Pn matches any value C V1 ... Vn where + each Vi matches Pi, + and binds the union of all variables bound in the subpatterns Pi +
  • a record pattern + { r1 = P1 ; ... ; r1 = P1 } + matches any record that has values of the corresponding fields. + and binds the union of all variables bound in the subpatterns Pi +
  • a variable pattern x + (identifier other than constant parameter) matches any value, and + binds x to this value +
  • the wild card _ matches any value +
  • a disjunctive pattern P | Q matches anything that + either P or Q matches; bindings must be the same in both +
  • a negative pattern -P matches anything that P does not match; + no bindings are returned +
  • an alias pattern x @ P matches whatever value P matches and + binds x to this value; also the bindings in P are returned +
+ +

+The following patterns are only available for the type Str: +

+
    +
  • a string literal pattern, e.g. "s", matches the same string +
  • a concatenation pattern P + Q matches any string that consists + of a prefix matching P and a suffix matching Q; + the union of bindings is returned +
  • a repetition pattern P* matches any string that can be decomposed + into strings that match P; no bindings are returned +
+ +

+The following pattern is only available for the types Int and Ints n: +

+
    +
  • an integer literal pattern, e.g. 214, matches the same integer +
+ +

+Pattern matching is performed in the order in which the branches +appear in the table: the branch of the first matching pattern is followed. +The type checker reject sets of patterns that are not exhaustive, and +warns for completely overshadowed patterns. +To guarantee exhaustivity when the infinite types Int and Str are +used as argument types, the last pattern must be a "catch-all" variable +or wild card. +

+

+It follows from the definition of record pattern matching +that it can utilize partial records: the branch +

+
+    {g = Fem} => t
+
+

+in a table of type {g : Gender ; n : Number} => T means the same as +

+
+    {g = Fem ; n = _} => t
+
+

+Variables in regular expression patterns +are always bound to the first match, which is the first +in the sequence of binding lists. For example: +

+
    +
  • x + "e" + y matches "peter" with x = "p", y = "ter" +
  • x + "er"* matches "burgerer" with ``x = "burg" +
+ + +

Overloading

+

+Judgements of the oper form can introduce overloaded functions. +The syntax is record-like, but all fields must have the same +name and different types. +

+
+    oper mkN = overload {
+      mkN : (dog : Str) -> Noun = regNoun ;
+      mkN : (mouse,mice : Str) -> Noun = mkNoun ;
+    }
+
+

+To give just the type of an overloaded operation, the record type +syntax is used. +

+
+    oper mkN : overload {
+      mkN : (dog : Str) -> Noun ;         -- regular nouns
+      mkN : (mouse,mice : Str) -> Noun ;  -- irregular nouns
+    }
+
+

+Overloading is not possible in other forms of judgement. +

+ +

Local definitions

+

+Local definitions ("let expressions") can appear in groups: +

+
+    oper regNoun : Str -> Noun = \vino -> 
+      let 
+        vin : Str = init vino ;
+        o   = last vino
+      in
+      ...
+
+

+The type can be omitted if it can be inferred. Later definitions may +refer to earlier ones. +

+ +

Supplementary constructs

+

+The rest of the GF language constructs are presented for the sake +of completeness. They will not be used in the rest of this tutorial. +

+

Record extension and subtyping

+

+Record types and records can be extended with new fields. For instance, +in German it is natural to see transitive verbs as verbs with a case, which +is usually accusative or dative, and is passed to the object of the verb. +The symbol ** is used for both record types and record objects. +

+
+    lincat TV = Verb ** {c : Case} ;
+  
+    lin Follow = regVerb "folgen" ** {c = Dative} ; 
+
+

+To extend a record type or a record with a field whose label it +already has is a type error. It is also an error to extend a type or +object that is not a record. +

+

+A record type T is a subtype of another one R, if T has +all the fields of R and possibly other fields. For instance, +an extension of a record type is always a subtype of it. +If T is a subtype of R, then R is a supertype of T. +

+

+If T is a subtype of R, an object of T can be used whenever +an object of R is required. +For instance, a transitive verb can be used whenever a verb is required. +

+

+Covariance means that a function returning a record T as value can +also be used to return a value of a supertype R. +Contravariance means that a function taking an R as argument +can also be applied to any object of a subtype T. +

+

Tuples and product types

+

+Product types and tuples are syntactic sugar for record types and records: +

+
+    T1 * ... * Tn   ===   {p1 : T1 ; ... ; pn : Tn}
+    <t1, ...,  tn>  ===   {p1 = T1 ; ... ; pn = Tn}
+
+

+Thus the labels p1, p2,... are hard-coded. +As patterns, tuples are translated to record patterns in the +same way as tuples to records; partial patterns make it +possible to write, slightly surprisingly, +

+
+    case <g,n,p> of {
+      <Fem> => t
+      ...
+      }
+
+

+

Prefix-dependent choices

+

+Sometimes a token has different forms depending on the token +that follows. An example is the English indefinite article, +which is an if a vowel follows, a otherwise. +Which form is chosen can only be decided at run time, i.e. +when a string is actually build. GF has a special construct for +such tokens, the pre construct exemplified in +

+
+    oper artIndef : Str = 
+      pre {"a" ; "an" / strs {"a" ; "e" ; "i" ; "o"}} ;
+
+

+Thus +

+
+    artIndef ++ "cheese"  --->  "a" ++ "cheese"
+    artIndef ++ "apple"   --->  "an" ++ "apple"
+
+

+This very example does not work in all situations: the prefix +u has no general rules, and some problematic words are +euphemism, one-eyed, n-gram. Since the branches are matched in +order, it is possible to write +

+
+    oper artIndef : Str = 
+      pre {"a" ; 
+           "a"  / strs {"eu" ; "one"} ;
+           "an" / strs {"a" ; "e" ; "i" ; "o" ; "n-"}
+          } ;
+
+

+Somewhat illogically, the default value is given as the first element in the list. +

+

+Prefix-dependent choice may be deprecated in GF version 3. +

+ +

Using the resource grammar library

+

+ +

+

+In this chapter, we will take a look at the GF resource grammar library. +We will use the library to implement the Foods grammar of the +previous chapter +and port it to some new languages. Some new concepts of GF's module system +are also introduced, most notably the technique of parametrized modules, +which has become an important "design pattern" for multilingual grammars. +

+ +

The coverage of the library

+

+The GF Resource Grammar Library contains grammar rules for +10 languages. In addition, 2 languages are available as yet incomplete +implementations, and a few more are under construction. The purpose +of the library is to define the low-level morphological and syntactic +rules of languages, and thereby enable application programmers +to concentrate on the semantic and stylistic +aspects of their grammars. The guiding principle is that +

+grammar checking becomes type checking +
+that is, whatever is type-correct in the resource grammar is also +grammatically correct. +

+

+The intended level of application grammarians +is that of a skilled programmer with +a practical knowledge of the target languages, but without +theoretical knowledge about their grammars. +Such a combination of +skills is typical of programmers who, for instance, want to localize +language software to new languages. +

+

+The current resource languages are +

+
    +
  • Arabic (incomplete) +
  • Catalan (incomplete) +
  • Danish +
  • English +
  • Finnish +
  • French +
  • German +
  • Italian +
  • Norwegian +
  • Russian +
  • Spanish +
  • Swedish +
+ +

+The first three letters (Eng etc) are used in grammar module names. +We use the three-letter codes for languages from the ISO 639 standard. +

+

+The incomplete Arabic and Catalan implementations are +sufficient for use in some applications; they both contain, amoung other +things, complete inflectional morphology. +

+ +

The structure of the library

+

+ +

+ +

Lexical vs. phrasal rules

+

+So far we have looked at grammars from a semantic point of view: +a grammar defines a system of meanings (specified in the abstract syntax) and +tells how they are expressed in some language (as specified in the concrete syntax). +In resource grammars, as often in the linguistic tradition, the goal is more modest: +to specify the grammatically correct combinations of words, whatever their +meanings are. With this more modest goal, it is possible to achieve a much +wider coverage than with semantic grammars. +

+

+Given the focus on words and their combinations, +the resource grammar has two kinds of categories and two kinds of rules: +

+
    +
  • lexical: +
      +
    • lexical categories, to classify words +
    • lexical rules, to define words and their properties +
    +
+ +
    +
  • phrasal (combinatorial, syntactic): +
      +
    • phrasal categories, to classify phrases of arbitrary size +
    • phrasal rules, to combine phrases into larger phrases +
    +
+ +

+Some grammar formalisms make a formal distinction between +the lexical and syntactic +components; sometimes it is necessary to use separate formalisms for these +two kinds of rules. GF has no such restrictions. +Nevertheless, it has turned out +to be a good discipline to maintain a distinction between +the lexical and syntactic components in the resource grammar. This fits +also well with what is needed in applications: while syntactic structures +are more or less the same across applications, vocabularies can be +very different. +

+ +

Lexical categories

+

+Within lexical categories, there is a further classification +into closed and open categories. The definining property +of closed categories is that the +words in them can easily be enumerated; it is very seldom that any +new words are introduced in them. In general, closed categories +contain structural words, also known as function words. +Examples of closed categories are +

+
+    QuantSg ;  -- singular quantifier   e.g. "this"
+    QuantPl ;  -- plural quantifier     e.g. "those"
+    AdA ;      -- adadjective           e.g. "very"
+
+

+We have already used words of all these categories in the Food +examples; they have just not been assigned a category, but +treated as syncategorematic. In GF, a syncategoramatic +word is one that is introduced in a linearization rule of +some construction alongside with some other expressions that +are combined; there is no abstract syntax tree for that word +alone. Thus in the rules +

+
+    fun That : Kind -> Item ;
+    lin That k = {"that" ++ k.s} ;
+
+

+the word that is syncategoramatic. In linguistically motivated +grammars, syncategorematic words are avoided, whereas in +semantically motivated grammars, structural words are typically treated +as syncategoramatic. This is partly so because the function expressed +by a structural word in one language is often expressed by some other +means than an individual word in another. For instance, the definite +article the is a determiner word in English, whereas Swedish expresses +determination by inflecting the determined noun: the wine is vinet +in Swedish. +

+

+As for open categories, we will start with these two: +

+
+    N ;    -- noun                  e.g. "pizza"
+    A ;    -- adjective             e.g. "good"
+
+

+Later in this chapter we will also need verbs of different kinds. +

+

+Note. Having adadjectives as a closed category is not quite right, because +one can form adadjectives from adjectives: incredibly warm. +

+ +

Lexical rules

+

+The words of closed categories can be listed once and for all in a +library. In the first example, the Foods grammar of the previous section, +we will use the following structural words from the Syntax module: +

+
+    this_QuantSg, that_QuantSg : QuantSg ; 
+    these_QuantPl, those_QuantPl : QuantPl ; 
+    very_AdA  : AdA ;
+
+

+The naming convention for lexical rules is that we use a word followed by +the category. In this way we can for instance distinguish the quantifier +that from the conjunction that. +

+

+Open lexical categories have no objects in Syntax. Such objects +will be built as they are needed in applications. The abstract +syntax of words in applications is already familiar, e.g. +

+
+    fun Wine : Kind ;
+
+

+The concrete syntax can be given directly, e.g. +

+
+    lin Wine = mkN "wine" ;
+
+

+by using the morphological paradigm library ParadigmsEng. +However, there are some advantages in giving the concrete syntax +indirectly, via the creation of a resource lexicon. In this lexicon, +there will be entries such as +

+
+    oper wine_N : N = mkN "wine" ;
+
+

+which can then be used in the linearization rules, +

+
+    lin Wine = wine_N ;
+
+

+One advantage of this indirect method is that each new word gives +an addition to a reusable resource lexicon, instead of just doing +the job of implementing the application. Another advantage will +be shown here: the possibility to write functors over +lexicon interfaces. +

+ +

Phrasal categories

+

+There are just four phrasal categories needed in the first application: +

+
+    Cl ;   -- clause             e.g. "this pizza is good"
+    NP ;   -- noun phrase        e.g. "this pizza"
+    CN ;   -- common noun        e.g. "warm pizza"
+    AP ;   -- adjectival phrase  e.g. "very warm"
+
+

+Clauses are, roughly, the same as declarative sentences; we will +define in here a sentence S as a clause that has a fixed tense. +The distinction between common nouns and noun phrases is that common nouns +cannot generally be used alone as subjects (?dog sleeps), +whereas noun phrases can (the dog sleeps). +Noun phrases can be built from common nouns by adding determiners, +such as quantifiers; but there are also other kinds of noun phrases, e.g. +pronouns. +

+

+The syntactic combinations we need are the following: +

+
+    mkCl : NP -> AP -> Cl ;      -- e.g. "this pizza is very warm"
+    mkNP : QuantSg -> CN -> NP ; -- e.g. "this pizza" 
+    mkNP : QuantPl -> CN -> NP ; -- e.g. "these pizzas"
+    mkCN : AP -> CN -> CN ;      -- e.g. "warm pizza"
+    mkAP : AdA -> AP -> AP ;     -- e.g. "very warm" 
+
+

+To start building phrases, we need rules of lexical insertion, which +form phrases from single words: +

+
+    mkCN : N -> NP ;
+    mkAP : A -> AP ;
+
+

+Notice that all (or, as many as possible) operations in the resource library +have the name mkC, where C is the value category of the operation. +This means of course heavy overloading. For instance, the current library +(version 1.2) has no less than 23 operations named mkNP! +

+

+Now the sentence +

+these very warm pizzas are Italian +
+can be built as follows: +

+
+    mkCl 
+      (mkNP these_QuantPl 
+         (mkCN (mkAP very_AdA (mkAP warm_A)) (mkCN pizza_CN)))
+      (mkAP italian_AP) 
+
+

+The task we are facing now is to define the concrete syntax of Foods so that +this syntactic tree gives the value of linearizing the semantic tree +

+
+    Is (These (QKind (Very Warm) Pizza)) Italian
+
+

+ +

The resource API

+

+The resource library API is divided into language-specific +and language-independent parts. To put it roughly, +

+
    +
  • the syntax API is language-independent, i.e. has the same types and + functions for all languages. + Its name is SyntaxL for each language L +
  • the morphology API is language-specific, i.e. has partly + different types and functions + for different languages. + Its name is ParadigmsL for each language L +
+ +

+A full documentation of the API is available on-line in the +resource synopsis. +For the examples of this chapter, we will only need a +fragment of the full API. The fragment needed for Foods has +already been introduced, but let us summarize the descriptions +by giving tables of the same form as used in the resource synopsis. +

+

+Thus we will make use of the following categories from the module Syntax. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryExplanationExample
Clclause (sentence), with all tensesshe looks at this
APadjectival phrasevery warm
CNcommon noun (without determiner)red house
NPnoun phrase (subject or object)the red house
AdAadjective-modifying adverb,very
QuantSgsingular quantifierthese
QuantPlplural quantifierthese
Aone-place adjectivewarm
Ncommon nounhouse
+ +

+

+We will use the following syntax rules from Syntax. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionTypeExample
mkClNP -> AP -> ClJohn is very old
mkNPQuantSg -> CN -> NPthis old man
mkNPQuantPl -> CN -> NPthese old man
mkCNN -> CNhouse
mkCNAP -> CN -> CNvery big blue house
mkAPA -> APold
mkAPAdA -> AP -> APvery very old
+ +

+

+We will use the following structural words from Syntax. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionTypeIn English
this_QuantSgQuantSgthis
that_QuantSgQuantSgthat
these_QuantPlQuantPlthis
those_QuantPlQuantPlthat
very_AdAAdAvery
+ +

+

+For English, we will use the following part of ParadigmsEng. +

+ + + + + + + + + + + + + + + + + +
FunctionType
mkN(dog : Str) -> N
mkN(man,men : Str) -> N
mkA(cold : Str) -> A
+ +

+

+For Italian, we need just the following part of ParadigmsIta +(Exercise). The "smart" paradigms will take care of variations +such as formaggio-formaggi, and also infer the genders +correctly. +

+ + + + + + + + + + + + + +
FunctionType
mkN(vino : Str) -> N
mkA(caro : Str) -> A
+ +

+

+For German, we will use the following part of ParadigmsGer. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionType
GenderType
masculineGender
feminineGender
neuterGender
mkN(Stufe : Str) -> N
mkN(Bild,Bilder : Str) -> Gender -> N
mkA(klein : Str) -> A
mkA(gut,besser,beste : Str) -> A
+ +

+

+For Finnish, we only need the smart regular paradigms: +

+ + + + + + + + + + + + + +
FunctionType
mkN(talo : Str) -> N
mkA(hieno : Str) -> A
+ +

+

+Exercise. Try out the morphological paradigms in different languages. Do +as follows: +

+
+    > i -path=alltenses:prelude -retain alltenses/ParadigmsGer.gfr
+    > cc mkN "Farbe"
+    > cc mkA "gut" "besser" "beste"
+
+

+ +

Example: English

+

+ +

+

+We work with the abstract syntax Foods from the fourth chapter, and +build first an English implementation. Now we can do it without +thinking about inflection and agreement, by just picking appropriate +functions from the resource grammar library. +

+

+The concrete syntax opens SyntaxEng and ParadigmsEng +to get access to the resource libraries needed. In order to find +the libraries, a path directive is prepended. It contains +two resource subdirectories --- present and prelude --- +which are found relative to the environment variable GF_LIB_PATH. +It also contains the current directory . and the directory ../foods, +in which Foods.gf resides. +

+
+    --# -path=.:../foods:present:prelude
+  
+    concrete FoodsEng of Foods = open SyntaxEng,ParadigmsEng in {
+
+

+As linearization types, we will use clauses for Phrase, noun phrases +for Item, common nouns for Kind, and adjectival phrases for Quality. +

+
+    lincat
+      Phrase = Cl ; 
+      Item = NP ;
+      Kind = CN ;
+      Quality = AP ;
+
+

+These types fit perfectly with the way we have used the categories +in the application; hence +the combination rules we need almost write themselves automatically: +

+
+    lin
+      Is item quality = mkCl item quality ;
+      This kind = mkNP this_QuantSg kind ;
+      That kind = mkNP that_QuantSg kind ;
+      These kind = mkNP these_QuantPl kind ;
+      Those kind = mkNP those_QuantPl kind ;
+      QKind quality kind = mkCN quality kind ;
+      Very quality = mkAP very_AdA quality ;
+
+

+We write the lexical part of the grammar by using resource paradigms directly. +Notice that we have to apply the lexical insertion rules to get type-correct +linearizations. Notice also that we need to use the two-place noun paradigm for +fish, but everythins else is regular. +

+
+      Wine = mkCN (mkN "wine") ;
+      Pizza = mkCN (mkN "pizza") ;
+      Cheese = mkCN (mkN "cheese") ;
+      Fish = mkCN (mkN "fish" "fish") ;
+      Fresh = mkAP (mkA "fresh") ;
+      Warm = mkAP (mkA "warm") ;
+      Italian = mkAP (mkA "Italian") ;
+      Expensive = mkAP (mkA "expensive") ;
+      Delicious = mkAP (mkA "delicious") ;
+      Boring = mkAP (mkA "boring") ;
+    }
+
+

+

+Exercise. Compile the grammar FoodsEng and generate +and parse some sentences. +

+

+Exercise. Write a concrete syntax of Foods for Italian +or some other language included in the resource library. You can +compare the results with the hand-written +grammars presented earlier in this tutorial. +

+ +

Functor implementation of multilingual grammars

+

+ +

+

+If you did the exercise of writing a concrete syntax of Foods for some other +language, you probably noticed that much of the code looks exactly the same +as for English. The reason for this is that the Syntax API is the +same for all languages. This is in turn possible because +all languages (at least those in the resource package) +implement the same syntactic structures. Moreover, languages tend to use the +syntactic structures in similar ways, even though this is not exceptionless. +But usually, it is only the lexical parts of a concrete syntax that +we need to write anew for a new language. Thus, to port a grammar to +a new language, you +

+
    +
  1. copy the concrete syntax of a given language +
  2. change the words (strings and inflection paradigms) +
+ +

+Now, programming by copy-and-paste is not worthy of a functional programmer! +So, can we write a function that takes care of the shared parts of grammar modules? +Yes, we can. It is not a function in the fun or oper sense, but +a function operating on modules, called a functor. This construct +is familiar from the functional programming +languages ML and OCaml, but it does not +exist in Haskell. It also bears some resemblance to templates in C++. +Functors are also known as parametrized modules. +

+

+In GF, a functor is a module that opens one or more interfaces. +An interface is a module similar to a resource, but it only +contains the types of opers, not their definitions. You can think +of an interface as a kind of a record type. The oper names are the +labels of this record type. The corresponding record is called an +instance of the interface. +Thus a functor is a module-level function taking instances as +arguments and producing modules as values. +

+

+Let us now write a functor implementation of the Food grammar. +Consider its module header first: +

+
+    incomplete concrete FoodsI of Foods = open Syntax, LexFoods in
+
+

+A functor is distinguished from an ordinary module by the leading +keyword incomplete. +

+

+In the functor-function analogy, FoodsI would be presented as a function +with the following type signature: +

+
+    FoodsI : 
+      instance of Syntax -> instance of LexFoods -> concrete of Foods
+
+

+It takes as arguments instances of two interfaces: +

+
    +
  • Syntax, the resource grammar interface +
  • LexFoods, the domain-specific lexicon interface +
+ +

+Functors opening Syntax and a domain lexicon interface are in fact +so typical in GF applications, that this structure could be called +a design pattern +for GF grammars. What makes this pattern so useful is, again, that +languages tend to use the same syntactic structures and only differ in words. +

+

+We will show the exact syntax of interfaces and instances in next Section. +Here it is enough to know that we have +

+
    +
  • SyntaxGer, an instance of Syntax +
  • LexFoodsGer, an instance of LexFoods +
+ +

+Then we can complete the German implementation by "applying" the functor: +

+
+    FoodI SyntaxGer LexFoodsGer : concrete of Foods
+
+

+The GF syntax for doing so is +

+
+    concrete FoodsGer of Foods = FoodsI with 
+      (Syntax = SyntaxGer),
+      (LexFoods = LexFoodsGer) ;
+
+

+Notice that this is the whole module, not just a header of it. +The module body is received from FoodsI, by instantiating the +interface constants with their definitions given in the German +instances. A module of this form, characterized by the keyword with, is +called a functor instantiation. +

+

+Here is the complete code for the functor FoodsI: +

+
+    --# -path=.:../foods:present:prelude
+  
+    incomplete concrete FoodsI of Foods = open Syntax, LexFoods in {
+    lincat
+      Phrase = Cl ; 
+      Item = NP ;
+      Kind = CN ;
+      Quality = AP ;
+    lin
+      Is item quality = mkCl item quality ;
+      This kind = mkNP this_QuantSg kind ;
+      That kind = mkNP that_QuantSg kind ;
+      These kind = mkNP these_QuantPl kind ;
+      Those kind = mkNP those_QuantPl kind ;
+      QKind quality kind = mkCN quality kind ;
+      Very quality = mkAP very_AdA quality ;
+  
+      Wine = mkCN wine_N ;
+      Pizza = mkCN pizza_N ;
+      Cheese = mkCN cheese_N ;
+      Fish = mkCN fish_N ;
+      Fresh = mkAP fresh_A ;
+      Warm = mkAP warm_A ;
+      Italian = mkAP italian_A ;
+      Expensive = mkAP expensive_A ;
+      Delicious = mkAP delicious_A ;
+      Boring = mkAP boring_A ;
+    }
+
+

+ +

Interfaces and instances

+

+ +

+

+Let us now define the LexFoods interface: +

+
+    interface LexFoods = open Syntax in {
+    oper
+      wine_N : N ;
+      pizza_N : N ;
+      cheese_N : N ;
+      fish_N : N ;
+      fresh_A : A ;
+      warm_A : A ;
+      italian_A : A ;
+      expensive_A : A ;
+      delicious_A : A ;
+      boring_A : A ;
+    }
+
+

+In this interface, only lexical items are declared. In general, an +interface can declare any functions and also types. The Syntax +interface does so. +

+

+Here is a German instance of the interface. +

+
+    instance LexFoodsGer of LexFoods = open SyntaxGer, ParadigmsGer in {
+    oper
+      wine_N = mkN "Wein" ;
+      pizza_N = mkN "Pizza" "Pizzen" feminine ;
+      cheese_N = mkN "Käse" "Käsen" masculine ;
+      fish_N = mkN "Fisch" ;
+      fresh_A = mkA "frisch" ;
+      warm_A = mkA "warm" "wärmer" "wärmste" ;
+      italian_A = mkA "italienisch" ;
+      expensive_A = mkA "teuer" ;
+      delicious_A = mkA "köstlich" ;
+      boring_A = mkA "langweilig" ;
+    }
+
+

+Notice that when an interface opens an interface, such as Syntax, +here, then its instance has to open an instance of it. But the instance +may also open some other resources --- very typically, like here, +a domain lexicon instance opens a Paradigms module. +

+

+Just to complete the picture, we repeat the German functor instantiation +for FoodsI, this time with a path directive that makes it compilable. +

+
+    --# -path=.:../foods:present:prelude
+  
+    concrete FoodsGer of Foods = FoodsI with 
+      (Syntax = SyntaxGer),
+      (LexFoods = LexFoodsGer) ;
+
+

+

+Exercise. Compile and test FoodsGer. +

+

+Exercise. Refactor FoodsEng into a functor instantiation. +

+ +

Adding languages to a functor implementation

+

+Once we have an application grammar defined by using a functor, +adding a new language is simple. Just two modules need to be written: +

+
    +
  • a domain lexicon instance +
  • a functor instantiation +
+ +

+The functor instantiation is completely mechanical to write. +Here is one for Finnish: +

+
+    --# -path=.:../foods:present:prelude
+  
+    concrete FoodsFin of Foods = FoodsI with 
+      (Syntax = SyntaxFin),
+      (LexFoods = LexFoodsFin) ;
+
+

+The domain lexicon instance requires some knowledge of the words of the +language: what words are used for which concepts, how the words are +inflected, plus features such as genders. Here is a lexicon instance for +Finnish: +

+
+    instance LexFoodsFin of LexFoods = open SyntaxFin, ParadigmsFin in {
+    oper
+      wine_N = mkN "viini" ;
+      pizza_N = mkN "pizza" ;
+      cheese_N = mkN "juusto" ;
+      fish_N = mkN "kala" ;
+      fresh_A = mkA "tuore" ;
+      warm_A = mkA "lämmin" ;
+      italian_A = mkA "italialainen" ;
+      expensive_A = mkA "kallis" ;
+      delicious_A = mkA "herkullinen" ;
+      boring_A = mkA "tylsä" ;
+    }
+
+

+

+Exercise. Instantiate the functor FoodsI to some language of +your choice. +

+ +

Division of labour revisited

+

+One purpose with the resource grammars was stated to be a division +of labour between linguists and application grammarians. We can now +reflect on what this means more precisely, by asking ourselves what +skills are required of grammarians working on different components. +

+

+Building a GF application starts from the abstract syntax. Writing +an abstract syntax requires +

+
    +
  • understanding of the semantic structure of the application domain +
  • knowledge of the GF fragment with categories and functions +
+ +

+If the concrete syntax is written by using a functor, the programmer +has to decide what parts of the implementation are put to the interface +and what parts are shared in the functor. This requires +

+
    +
  • knowing how the domain concepts are expressed in natural language +
  • knowledge of the resource grammar library --- the categories and combinators +
  • understanding what parts are likely to be expressed in language-dependent + ways, so that they are put to an interface and not the functor +
  • knowledge of the GF fragment with function applications and strings +
+ +

+Instantiating a ready-made functor to a new language is less demanding. +It requires essentially +

+
    +
  • knowing how the domain words are expressed in the language +
  • knowing, roughly, how these words are inflected +
  • knowledge of the paradigms available in the library +
  • knowledge of the GF fragment with function applications and strings +
+ +

+Notice that none of these tasks requires the use of GF records, tables, +or parameters. Thus only a small fragment of GF is needed; the rest of +GF is only relevant for those who write the libraries. Essentially, +all the machinery introduced in the fourth chapter is unnecessary! +

+

+Of course, grammar writing is not always just straightforward usage of libraries. +For example, GF can be used for other languages than just those in the +libraries --- for both natural and formal languages. A knowledge of records +and tables can, unfortunately, also be needed for understanding GF's error +messages. +

+

+Exercise. Design a small grammar that can be used for controlling +an MP3 player. The grammar should be able to recognize commands such +as play this song, with the following variations: +

+
    +
  • verbs: play, remove +
  • objects: song, artist +
  • determiners: this, the previous +
  • verbs without arguments: stop, pause +
+ +

+The implementation goes in the following phases: +

+
    +
  1. abstract syntax +
  2. functor and lexicon interface +
  3. lexicon instance for the first language +
  4. functor instantiation for the first language +
  5. lexicon instance for the second language +
  6. functor instantiation for the second language +
  7. ... +
+ + +

Restricted inheritance

+

+A functor implementation using the resource Syntax interface +works well as long as all concepts are expressed by using the same structures +in all languages. If this is not the case, the deviant linearization can +be made into a parameter and moved to the domain lexicon interface. +

+

+The Foods grammar works so well that we have to +take a contrived example: assume that English has +no word for Pizza, but has to use the paraphrase Italian pie. +This paraphrase is no longer a noun N, but a complex phrase +in the category CN. An obvious way to solve this problem is +to change interface LexFoods so that the constant declared for +Pizza gets a new type: +

+
+    oper pizza_CN : CN ;
+
+

+But this solution is unstable: we may end up changing the interface +and the function with each new language, and we must every time also +change the interface instances for the old languages to maintain +type correctness. +

+

+A better solution is to use restricted inheritance: the English +instantiation inherits the functor implementation except for the +constant Pizza. This is how we write: +

+
+    --# -path=.:../foods:present:prelude
+  
+    concrete FoodsEng of Foods = FoodsI - [Pizza] with 
+      (Syntax = SyntaxEng),
+      (LexFoods = LexFoodsEng) ** 
+        open SyntaxEng, ParadigmsEng in {
+  
+      lin Pizza = mkCN (mkA "Italian") (mkN "pie") ;
+    }
+
+

+Restricted inheritance is available for all inherited modules. One can for +instance exclude some mushrooms and pick up just some fruit in +the FoodMarket example "Rsecarchitecture: +

+
+    abstract Foodmarket = Food, Fruit [Peach], Mushroom - [Agaric]
+
+

+A concrete syntax of Foodmarket must then have the same inheritance +restrictions, in order to be well-typed with respect to the abstract syntax. +

+ +

Grammar reuse

+

+The alert reader has certainly noticed an analogy between abstract +and concrete, on the one hand, and interface and instance, +on the other. Why are these two pairs of module types kept separate +at all? There is, in fact, a very close correspondence between +judgements in the two kinds of modules: +

+
+    cat C         <--->  oper C : Type
+  
+    fun f : A     <--->  oper f : A
+  
+    lincat C = T  <--->  oper C : Type = T
+  
+    lin f = t     <--->  oper f : A = t
+
+

+But there are also some differences: +

+
    +
  • abstract and concrete modules define top-level grammars, i.e. + grammars that can be used for parsing and linearization; this is because +
  • the types and terms in concrete modules are restricted to a subset + of those available in interface, instance, and resource +
  • param judgements have no counterparts in top-level grammars +
+ +

+The term that can be used for interfaces, instances, and resources is +resource-level grammars. +From these explanations and the above translations it follows that top-level +grammars are, in a sense, a special case of resource-level grammars. +

+

+Thus, indeed, abstract syntax modules can be used like interfaces, and concrete syntaxes +as their instances. The use of top-level grammars as resources +is called grammar reuse. Whether a library module is a top-level or a +resource-level module is mostly invisible to application programmers +(see the Summary here +for an exception to this). The GF resource grammar +library itself is in fact built in two layers: +

+
    +
  • the ground resource: a set of top-level grammars for syntactic structures +
  • the surface resource: a resource-level grammar with overloaded operations + defined in terms of the ground resource +
+ +

+Both the ground +resource and the surface resource can be used by application programmers, +but it is the surface resource that we use in this book. Because of overloading, +it has much fewer function names and also flatter trees. For instance, the clause +

+these very warm pizzas are Italian +
+which in the surface resource can be built as +

+
+    mkCl 
+      (mkNP these_QuantPl 
+        (mkCN (mkAP very_AdA (mkAP warm_A)) (mkCN pizza_CN)))
+      (mkAP italian_AP) 
+
+

+has in the ground resource the much more complex tree +

+
+    PredVP 
+      (DetCN (DetPl (PlQuant this_Quant) NoNum NoOrd) 
+        (AdjCN (AdAP very_AdA (PositA warm_A)) (UseN pizza_N))) 
+      (UseComp (CompAP (PositA italian_A)))
+
+

+The main advantage of using the ground resource is that the trees can then be found +by using the parser, as shown in the next section. Otherwise, the overloaded surface +resource constants are much easier to use. +

+

+Needless to say, once a library has been defined in some way, it is easy to +build layers of derived libraries on top of it, by using grammar reuse +and, in the case of multilingual libraries, functors. This is indeed how +the surface resource has been implemented: as a functored parametrized on +the abstract syntax of the ground resource. +

+ +

Browsing the resource with GF commands

+

+ +

+

+In addition to reading the +resource synopsis, you +can find resource function combinations by using the parser. This +is so because the resource library is in the end implemented as +a top-level abstract-concrete grammar, on which parsing +and linearization work. +

+

+Unfortunately, currently (GF 2.8) +only English and the Scandinavian languages can be +parsed within acceptable computer resource limits when the full +resource is used. +

+

+To look for a syntax tree in the overload API by parsing, do like this: +

+
+    % gf -path=alltenses:prelude $GF_LIB_PATH/alltenses/OverLangEng.gfc
+  
+    > p -cat=S -overload "this grammar is too big"
+    mkS (mkCl (mkNP this_QuantSg grammar_N) (mkAP too_AdA big_A))
+
+

+The -overload option given to the parser is a directive to find the +shallowest overloaded term that matches the parse tree. +

+

+To view linearizations in all languages by parsing from English: +

+
+    % gf $GF_LIB_PATH/alltenses/langs.gfcm
+  
+    > p -cat=S -lang=LangEng "this grammar is too big" | tb
+    UseCl TPres ASimul PPos (PredVP (DetCN (DetSg (SgQuant this_Quant) 
+      NoOrd) (UseN grammar_N)) (UseComp (CompAP (AdAP too_AdA (PositA big_A)))))
+    Den här grammatiken är för stor
+    Esta gramática es demasiado grande
+    (Cyrillic: eta grammatika govorit des'at' jazykov)
+    Denne grammatikken er for stor
+    Questa grammatica è troppo grande
+    Diese Grammatik ist zu groß
+    Cette grammaire est trop grande
+    Tämä kielioppi on liian suuri
+    This grammar is too big
+    Denne grammatik er for stor
+
+

+This method shows the unambiguous ground resource functions and not +the overloaded ones. It uses a precompiled grammar package of the GFCM or GFCC +format; see the eighth chapter for more information on this. +

+

+Unfortunately, the Russian grammar uses at the moment a different +character encoding than the rest and is therefore not displayed correctly +in a terminal window. However, the GF syntax editor does display all +examples correctly --- again, using the ground resource: +

+
+    % gfeditor $GF_LIB_PATH/alltenses/langs.gfcm
+
+

+When you have constructed the tree, you will see the following screen: +

+

+

+

+

+ +

+

+

+

+

+Exercise. Find the resource grammar translations for the following +English phrases (parse in the category Phr). You can first try to +build the terms manually. +

+

+every man loves a woman +

+

+this grammar speaks more than ten languages +

+

+which languages aren't in the grammar +

+

+which languages did you want to speak +

+ +

An extended Foods grammar

+

+ +

+

+Now that we know how to find information in the resource grammar, +we can easily extend the Foods fragment considerably. We shall enable +the following new expressions: +

+
    +
  • questions: Is this pizza Italian? Which pizza do you want to eat? +
  • imperatives: Eat that pizza please! +
  • denials: These pizzas are not Italian. +
  • verbs: eat, pay +
  • guests, in addition to food items: I, you, this lady +
+ + +

Abstract syntax

+

+Since we don't want to change the already existing Foods module, +we build an extension of it, ExtFoods: +

+
+    abstract ExtFoods = Foods ** {
+  
+    flags startcat=Move ;
+  
+    cat
+      Move ;      -- dialogue move: declarative, question, or imperative
+      Verb ;      -- transitive verb
+      Guest ;     -- guest in restaurant
+      GuestKind ; -- type of guest
+  
+    fun
+      MAssert : Phrase -> Move ;  -- This pizza is warm.
+      MDeny : Phrase -> Move ;    -- This pizza isn't warm.
+      MAsk : Phrase -> Move ;     -- Is this pizza warm?
+  
+      PVerb : Guest -> Verb -> Item -> Phrase ;     -- we eat this pizza
+      PVerbWant : Guest -> Verb -> Item -> Phrase ; -- we want to eat this pizza
+  
+      WhichVerb : 
+        Kind -> Guest -> Verb -> Move ;   -- Which pizza do you eat?
+      WhichVerbWant : 
+        Kind -> Guest -> Verb -> Move ;   -- Which pizza do you want to eat?
+      WhichIs : Kind -> Quality -> Move ; -- Which wine is Italian? 
+  
+      Do : Verb -> Item -> Move ;         -- Pay this wine!
+      DoPlease : Verb -> Item -> Move ;   -- Pay this wine please!
+  
+      I, You, We : Guest ;
+  
+      GThis, GThat, GThese, GThose : GuestKind -> Guest ;
+      
+      Eat, Drink, Pay : Verb ;
+  
+      Lady, Gentleman : GuestKind ;    
+    }
+
+

+The concrete syntax is implemented by a functor that extends the +already defined functor FoodsI. +

+
+    incomplete concrete ExtFoodsI of ExtFoods = 
+              FoodsI ** open Syntax, LexFoods in {
+  
+      flags lexer=text ; unlexer=text ;
+
+

+The flags set up a lexer and unlexer that can deal with sentence-initial +capital letters and proper spacing with punctuation (see here +for more information on lexers and unlexers). +

+ +

Linearization types

+

+If we look at the resource documentation, we find several categories +that are above the clause level and can thus host different kinds +of dialogue moves: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryExplanationExample
Texttext consisting of phrasesHe is here. Why?
Phrphrase in a textbut be quiet please
Uttsentence, question, word...be quiet
Sdeclarative sentenceshe lived here
QSquestionwhere did she live
Impimperativelook at this
QClquestion clause, with all tenseswhy does she walk
+ +

+

+We also find that only the category Text contains punctuation marks. +So we choose this as the linearization type of Move. The other types +are quite obvious. +

+
+    lincat
+      Move = Text ;
+      Verb = V2 ;
+      Guest = NP ;
+      GuestKind = CN ;
+
+

+The category V2 of two-place verbs includes both +transitive verbs that take direct objects (e.g. we watch him) +and verbs that take other kinds of complements, often with +prepositions (we look at him). In a multilingual grammar, it is +not guaranteed that transitive verbs are transitive in all languages, +so the more general notion of two-place verb is more appropriate. +

+ +

Linearization rules

+

+Now we need to find constructors that combine the new categories in +appropriate ways. To form a text from a clause, we first make it into +a sentence with mkS, and then apply mkText: +

+
+    lin MAssert p = mkText (mkS p) ;
+
+

+The function mkS has in the resource synopsis been given the type +

+
+    mkS : (Tense) -> (Ant) -> (Pol) -> Cl -> S
+
+

+Parentheses around type names do not make any difference for the GF compiler, +but in the synopsis notation they indicate optionality: any of the +optional arguments can be omitted, and there is an instance of mkS +available. For each optional type, it uses the default value for that +type, which for the polarity Pol is positive i.e. unnegated. +To build a negative sentence, we use an explicit polarity constructor: +

+
+      MDeny p = mkText (mkS negativePol p) ;
+
+

+Of course, we could have used positivePol in the first rule, instead of +relying on the default. (The types Tense and Ant will be explained +here.) +

+

+Phrases can be made into question sentences, which in turn can be +made into texts in a similar way as sentences; the default +punctuation mark is not the full stop but the question mark. +

+
+      MAsk p = mkText (mkQS p) ;
+
+

+There is an mkCl instance that directly builds a clause from a noun phrase, +a two-place verb, and another noun phrase. +

+
+      PVerb = mkCl ;
+
+

+The auxiliary verb want requires a verb phrase (VP) as its complement. It +can be built from a two-place verb and its noun phrase complement. +

+
+      PVerbWant guest verb item = mkCl guest want_VV (mkVP verb item) ;
+
+

+The interrogative determiner (IDet) which can be combined with +a common noun to form an interrogative phrase (IP). This IP can then +be used as a subject in a question clause (QCl), which in turn is +made into a QS and finally to a Text. +

+
+      WhichIs kind quality = 
+        mkText (mkQS (mkQCl (mkIP whichSg_IDet kind) (mkVP quality))) ;
+
+

+When interrogative phrases are used as objects, the resource library +uses a category named Slash of +objectless sentences. The name cames from the slash categories of the +GPSG grammar formalism +(Gazdar & al. 1985). Slashes can be formed from subjects and two-place verbs, +also with an intervening auxiliary verb. +

+
+      WhichVerb kind guest verb = 
+        mkText (mkQS (mkQCl (mkIP whichSg_IDet kind)
+          (mkSlash guest verb))) ;
+      WhichVerbWant kind guest verb = 
+        mkText (mkQS (mkQCl (mkIP whichSg_IDet kind) 
+          (mkSlash guest want_VV verb))) ;
+
+

+Finally, we form the imperative (Imp) of a transitive verb +and its object. We make it into a polite form utterance, and finally +into a Text with an exclamation mark. +

+
+      Do verb item = 
+        mkText 
+          (mkPhr (mkUtt politeImpForm (mkImp verb item))) exclMarkPunct ;
+      DoPlease verb item = 
+        mkText 
+          (mkPhr (mkUtt politeImpForm (mkImp verb item)) please_Voc) 
+          exclMarkPunct ;
+
+

+The rest of the concrete syntax is straightforward use of structural words, +

+
+      I = mkNP i_Pron ;
+      You = mkNP youPol_Pron ;
+      We = mkNP we_Pron ;
+      GThis = mkNP this_QuantSg ;
+      GThat = mkNP that_QuantSg ;
+      GThese = mkNP these_QuantPl ;
+      GThose = mkNP those_QuantPl ;
+
+

+and of the food lexicon, +

+
+      Eat = eat_V2 ;
+      Drink = drink_V2 ;
+      Pay = pay_V2 ;
+      Lady = lady_N ;
+      Gentleman = gentleman_N ;
+  }
+
+

+Notice that we have no reason to build an extension of LexFoods, but we just +add words to the old one. Since LexFoods instances are resource modules, +the superfluous definitions that they contain have no effect on the +modules that just open them, and thus the smaller Foods grammars +don't suffer from the additions we make. +

+

+Exercise. Port the ExtFoods grammars to some new languages, building +on the Foods implementations from previous sections, and using the functor +defined in this section. +

+ +

Tenses

+

+ +

+

+When compiling the ExtFoods grammars, we have used the path +

+
+    --# -path=.:../foods:present:prelude
+
+

+where the library subdirectory present refers to a restricted version +of the resource that covers only the present tense of verbs and sentences. +Having this version available is motivatad by efficiency reasons: tenses +produce in many languages a manifold of forms and combinations, which +multiply the size of the grammar; at the same time, many applications, +both technical ones and spoken dialogues, only need the present tense. +

+

+But it is easy change the grammars so that they admit of the full set +of tenses. It is enough to change the path to +

+
+    --# -path=.:../foods:alltenses:prelude
+
+

+and recompile the grammars from source (flag -src); the libraries are +not recompiled, because their sources cannot be found on the path list. +Then it is possible to see all the tenses of +phrases, by using the -all flag in linearization: +

+
+    > gr -cat=Phrase | l -all
+    This wine is delicious
+    Is this wine delicious
+    This wine isn't delicious
+    Isn't this wine delicious
+    This wine is not delicious
+    Is this wine not delicious
+    This wine has been delicious
+    Has this wine been delicious
+    This wine hasn't been delicious
+    Hasn't this wine been delicious
+    This wine has not been delicious
+    Has this wine not been delicious
+    This wine was delicious
+    Was this wine delicious
+    This wine wasn't delicious
+    Wasn't this wine delicious
+    This wine was not delicious
+    Was this wine not delicious
+    This wine had been delicious
+    Had this wine been delicious
+    This wine hadn't been delicious
+    Hadn't this wine been delicious
+    This wine had not been delicious
+    Had this wine not been delicious
+    This wine will be delicious
+    Will this wine be delicious
+    This wine won't be delicious
+    Won't this wine be delicious
+    This wine will not be delicious
+    Will this wine not be delicious
+    This wine will have been delicious
+    Will this wine have been delicious
+    This wine won't have been delicious
+    Won't this wine have been delicious
+    This wine will not have been delicious
+    Will this wine not have been delicious
+    This wine would be delicious
+    Would this wine be delicious
+    This wine wouldn't be delicious
+    Wouldn't this wine be delicious
+    This wine would not be delicious
+    Would this wine not be delicious
+    This wine would have been delicious
+    Would this wine have been delicious
+    This wine wouldn't have been delicious
+    Wouldn't this wine have been delicious
+    This wine would not have been delicious
+    Would this wine not have been delicious
+
+

+In addition to tenses, the linearization writes all parametric +variations --- polarity and word order (direct vs. inverted) --- as +well as the variation between contracted and full negation words. +Of course, the list is even longer in languages that have more +tenses and moods, e.g. the Romance languages. +

+

+In the ExtFoods grammar, tenses never find their way to the +top level of Moves. Therefore it is useless to carry around +the clause and verb tenses given in the alltenses set of libraries. +But with the library, it is easy to add tenses to Moves. For +instance, one can add the rules +

+
+    fun MAssertFut      : Phrase -> Move ;  -- I will pay this wine
+    fun MAssertPastPerf : Phrase -> Move ;  -- I had paid that wine
+    lin MAssertFut p = mkText (mkS futureTense p) ;
+    lin MAssertPastPerf p = mkText (mkS pastTense anteriorAnt p) ;
+
+

+Comparison with MAssert above shows that the absence of the tense +and anteriority features defaults to present simultaneous tenses. +

+

+Exercise. Measure the size of the context-free grammar corresponding to +some concrete syntax of ExtFoods with all tenses. +You can do this by printing the grammar in the context-free format +(print_grammar -printer=cfg) and counting the lines. +

+ +

Summary of GF language features

+ +

Interfaces and instances

+

+An interface module (interface I) is like a resource module, +the difference being that it does not need to give definitions in +its oper and param judgements. Definitions are, however, +allowed, and they may use constants that appear undefined in the +module. For example, here is an interface for predication, which +is parametrized on NP case and agreement features, and on the constituent +order: +

+
+    interface Predication = {
+      param 
+        Case ;
+        Agreement ;
+      oper 
+        subject : Case ;
+        object : Case ;
+        order : (verb,subj,obj : String) -> String ;
+  
+        NP : Type = {s : Case => Str ; a : Agreement} ;
+        TV : Type = {s : Agreement => Str} ;
+  
+        sentence : TV -> NP -> NP -> {s : Str} = \verb,subj,obj -> {
+          s = order (verb ! subj.a) (subj ! subject) (obj ! object) ;
+    }
+
+

+An instance module (instance J of I) is also like a +resource, but it is compiled in union with the interface that it +is an instance of. This means that the definitions given in the +instance are type-checked with respect to the types given in the +interface. Moreover, overwriting types or definitions given in the interface +is not allowed. But it is legal for an instance to contain definitions +not included in the corresponding interface. Here is an instance of +Predication, suitable for languages like English. +

+
+    instance PredicationSimpleSVO of Predication = {
+      param 
+        Case = Nom | Acc | Gen ;
+        Agreement = Agr Number Person ;
+  
+        -- two new types     
+        Number = Sg | Pl ;
+        Person = P1 | P2 | P3 ;
+  
+      oper 
+        subject = Nom ;
+        object = Acc ;
+        order = \verb,subj,obj -> subj ++ verb ++ obj ;
+  
+        -- the rest of the definitions don't need repetition
+    }
+
+

+ +

Grammar reuse

+

+ +

+

+Abstract syntax modules can be used like interfaces, and concrete syntaxes +as their instances. The following translations then take place: +

+
+    cat C         ---> oper C : Type
+  
+    fun f : A     ---> oper f : A*
+  
+    lincat C = T  ---> oper C : Type = T'
+  
+    lin f = t     ---> oper f : A* = t'
+
+

+This translation is called grammar reuse. It uses a homomorphism +from abstract types and terms to the concrete types and terms. For the +sake of more type safety, the types are not exactly the same. Currently +(GF 2.8), the type T' formed from the linearization type T of +a category C is T extended with a dummy lock field. Thus +

+
+    lincat C = T  ---> oper C = T ** {lock_C : {}}
+
+

+and the linearization terms are lifted correspondingly. The user of +a GF library should never see any lock fields; when they appear in +the compiler's warnings, they indicate that some library category is +constructed improperly by a user program. +

+ +

Functors

+

+A parametrized module, aka. an incomplete module, or a +functor, is any module that opens an interface (or +an abstract). Several interfaces may be opened by one +functor. The module header must be prefixed by the word incomplete. +Here is a typical example, using the resource Syntax and +a domain specific lexicon: +

+
+    incomplete concrete DomainI of Domain = open Syntax, Lex in {...} ;
+
+

+A functor instantiation is a module that inherits a functor and +provides an instance to each of its open interfaces. Here is an example: +

+
+    concrete DomainSwe of Domain = DomainI with
+      (Syntax = SyntaxSwe),
+      (Lex = LexSwe) ;
+
+

+ +

Restricted inheritance

+

+A module of any type can make restricted inheritance, which is +either exclusion or inclusion: +

+
+    module M = A[f,g], B-[k] ** ...
+
+

+A concrete syntax given to an abstract syntax that uses restricted inheritance +must make the corresponding restrictions. In addition, the concrete syntax can +make its own restrictions in order to redefine inherited linearization types and +rules. +

+

+Overriding old definitions without explicit restrictions is not allowed. +

+ +

Refining semantics in abstract syntax

+

+ +

+

+While the concrete syntax constructs of GF have been already +covered, there is much more that can be done in the abstract +syntax. The techniques of dependent types and +higher order abstract syntax are introduced in this chapter, +which thereby concludes the presentation of the GF language. +

+

+Many of the examples in this chapter are somewhat less close to +applications than the ones shown before. Moreover, the tools for +embedded grammars in the eighth chapter do not yet fully support dependent +types and higher order abstract syntax. +

+ +

GF as a logical framework

+

+In this chapter, we will show how +to encode advanced semantic concepts in an abstract syntax. +We use concepts inherited from type theory. Type theory +is the basis of many systems known as logical frameworks, which are +used for representing mathematical theorems and their proofs on a computer. +In fact, GF has a logical framework as its proper part: +this part is the abstract syntax. +

+

+In a logical framework, the formalization of a mathematical theory +is a set of type and function declarations. The following is an example +of such a theory, represented as an abstract module in GF. +

+
+  abstract Arithm = {
+    cat
+      Prop ;                        -- proposition
+      Nat ;                         -- natural number
+    fun
+      Zero : Nat ;                  -- 0
+      Succ : Nat -> Nat ;           -- the successor of x
+      Even : Nat -> Prop ;          -- x is even
+      And  : Prop -> Prop -> Prop ; -- A and B
+      } 
+
+

+This example does not show any new type-theoretical constructs yet, but +it could nevertheless be used as a part of a proof system for arithmetic. +

+

+Exercise. Give a concrete syntax of Arithm, preferably +by using the resource library. +

+ +

Dependent types

+

+ +

+

+Dependent types are a characteristic feature of GF, +inherited from the constructive type theory of Martin-Löf and +distinguishing GF from most other grammar formalisms and +functional programming languages. +

+

+Dependent types can be used for stating stronger +conditions of well-formedness than ordinary types. +A simple example is a "smart house" system, which +defines voice commands for household appliances. This example +is borrowed from the +Regulus Book +(Rayner & al. 2006). +

+

+One who enters a smart house can use a spoken Command to dim lights, switch +on the fan, etc. For Devices of each Kind, there is a set of +Actions that can be performed on them; thus one can dim the lights but + not the fan, for example. These dependencies can be expressed +by making the type Action dependent on Kind. We express these +dependencies in cat declarations by attaching argument types to +categories: +

+
+    cat
+      Command ;
+      Kind ; 
+      Device Kind ; -- argument type Kind 
+      Action Kind ; 
+
+

+The crucial use of the dependencies is made in the rule for forming commands: +

+
+    fun CAction : (k : Kind) -> Action k -> Device k -> Command ;
+
+

+In other words: an action and a device can be combined into a command only +if they are of the same Kind k. If we have the functions +

+
+    DKindOne  : (k : Kind) -> Device k ;  -- the light
+  
+    light, fan : Kind ;
+    dim : Action light ;
+
+

+we can form the syntax tree +

+
+    CAction light dim (DKindOne light)
+
+

+but we cannot form the trees +

+
+    CAction light dim (DKindOne fan)
+    CAction fan   dim (DKindOne light)
+    CAction fan   dim (DKindOne fan)
+
+

+Linearization rules are written as usual: the concrete syntax does not +know if a category is a dependent type. In English, one could write as follows: +

+
+    lincat Action = {s : Str} ;
+    lin CAction _ act dev = {s = act.s ++ dev.s} ; 
+
+

+Notice that the argument for Kind does not appear in the linearization; +therefore it is good practice to make this clear by +using a wild card for it, rather than a real +variable. +As we will show, +the type checker can reconstruct the kind from the dev argument. +

+

+Parsing with dependent types is performed in two phases: +

+
    +
  1. context-free parsing +
  2. filtering through type checker +
+ +

+If you just parse in the usual way, you don't enter the second phase, and +the kind argument is not found: +

+
+    > parse "dim the light"
+    CAction ? dim (DKindOne light)
+
+

+Moreover, type-incorrect commands are not rejected: +

+
+    > parse "dim the fan"
+    CAction ? dim (DKindOne fan)
+
+

+The question mark ? is a metavariable, and is returned by the parser +for any subtree that is suppressed by a linearization rule. +These are exactly the same kind of metavariables as were used here +to mark incomplete parts of trees in the syntax editor. +

+

+To get rid of metavariables, we must feed the parse result into the +second phase of solving them. The solve process uses the dependent +type checker to restore the values of the metavariables. It is invoked by +the command put_tree = pt with the flag -transform=solve: +

+
+    > parse "dim the light" | put_tree -transform=solve
+    CAction light dim (DKindOne light)
+
+

+The solve process may fail, in which case no tree is returned: +

+
+    > parse "dim the fan" | put_tree -transform=solve
+    no tree found
+
+

+

+Exercise. Write an abstract syntax module with above contents +and an appropriate English concrete syntax. Try to parse the commands +dim the light and dim the fan, with and without solve filtering. +

+

+Exercise. Perform random and exhaustive generation, with and without +solve filtering. +

+

+Exercise. Add some device kinds and actions to the grammar. +

+ +

Polymorphism

+

+ +

+

+Sometimes an action can be performed on all kinds of devices. It would be +possible to introduce separate fun constants for each kind-action pair, +but this would be tedious. Instead, one can use polymorphic actions, +i.e. actions that take a Kind as an argument and produce an Action +for that Kind: +

+
+    fun switchOn, switchOff : (k : Kind) -> Action k ;
+
+

+Functions that are not polymorphic are monomorphic. However, the +dichotomy into monomorphism and full polymorphism is not always sufficient +for good semantic modelling: very typically, some actions are defined +for a proper subset of devices, but not just one. For instance, both doors and +windows can be opened, whereas lights cannot. +We will return to this problem by introducing the +concept of restricted polymorphism later, +after a section on proof objects. +

+

+Exercise. The grammar ExtFoods here permits the +formation of phrases such as we drink this fish and we eat this wine. +A way to prevent them is to distinguish between eatable and drinkable food items. +Another, related problem is that there is some duplicated code +due to a category distinction between guests and food items, for instance, +two constructors for the determiner this. This problem can also +be solved by dependent types. Rewrite the abstract syntax in Foods and +ExtFoods by using such a type system, and also update the concrete syntaxes. +If you do this right, you only have to change the functor modules +FoodsI and ExtFoodsI in the concrete syntax. +

+ +

Digression: dependent types in concrete syntax

+

+The functional fragment of GF +terms and types comprises function types, applications, lambda +abstracts, constants, and variables. This fragment is the same in +abstract and concrete syntax. In particular, +dependent types are also available in concrete syntax. +We have not made use of them yet, +but we will now look at one example of how they +can be used. +

+

+Those readers who are familiar with functional programming languages +like ML and Haskell, may already have missed polymorphic +functions. For instance, Haskell programmers have access to +the functions +

+
+    const :: a -> b -> a
+    const c _ = c
+  
+    flip :: (a -> b -> c) -> b -> a -> c
+    flip f y x = f x y
+
+

+which can be used for any given types a,b, and c. +

+

+The GF counterpart of polymorphic functions are monomorphic +functions with explicit type variables --- a techniques that we already +used in abstract syntax for modelling actions that can be performed +on all kinds of devices. Thus the above definitions can be written +

+
+    oper const :(a,b : Type) -> a -> b -> a =
+      \_,_,c,_ -> c ;
+  
+    oper flip : (a,b,c : Type) -> (a -> b ->c) -> b -> a -> c =
+      \_,_,_,f,x,y -> f y x ;
+
+

+When the operations are used, the type checker requires +them to be equipped with all their arguments; this may be a nuisance +for a Haskell or ML programmer. They have not been used very much, +except in the Coordination module of the resource library. +

+ +

Proof objects

+

+Perhaps the most well-known idea in constructive type theory is +the Curry-Howard isomorphism, also known as the +propositions as types principle. Its earliest formulations +were attempts to give semantics to the logical systems of +propositional and predicate calculus. In this section, we will consider +a more elementary example, showing how the notion of proof is useful +outside mathematics, as well. +

+

+We use the already shown category of unary (also known as Peano-style) +natural numbers: +

+
+    cat Nat ; 
+    fun Zero : Nat ;
+    fun Succ : Nat -> Nat ;
+
+

+The successor function Succ generates an infinite +sequence of natural numbers, beginning from Zero. +

+

+We then define what it means for a number x to be less than +a number y. Our definition is based on two axioms: +

+
    +
  • Zero is less than Succ y for any y. +
  • If x is less than y, then Succ x is less than Succ y. +
+ +

+The most straightforward way of expressing these axioms in type theory +is with a dependent type Less x y, and two functions constructing +its objects: +

+
+    cat Less Nat Nat ; 
+    fun lessZ : (y : Nat) -> Less Zero (Succ y) ;
+    fun lessS : (x,y : Nat) -> Less x y -> Less (Succ x) (Succ y) ;
+
+

+Objects formed by lessZ and lessS are +called proof objects: they establish the truth of certain +mathematical propositions. +For instance, the fact that 2 is less that +4 has the proof object +

+
+    lessS (Succ Zero) (Succ (Succ (Succ Zero)))
+          (lessS Zero (Succ (Succ Zero)) (lessZ (Succ Zero)))
+
+

+whose type is +

+
+    Less (Succ (Succ Zero)) (Succ (Succ (Succ (Succ Zero))))
+
+

+which is the formalization of the proposition that 2 is less than 4. +

+

+GF grammars can be used to provide a semantic control of +well-formedness of expressions. We have already seen examples of this: +the grammar of well-formed actions on household devices. By introducing proof objects +we have now added an even more powerful technique of expressing semantic conditions. +

+

+A simple example of the use of proof objects is the definition of +well-formed time spans: a time span is expected to be from an earlier to +a later time: +

+
+    from 3 to 8
+
+

+is thus well-formed, whereas +

+
+    from 8 to 3
+
+

+is not. The following rules for spans impose this condition +by using the Less predicate: +

+
+    cat Span ;
+    fun span : (m,n : Nat) -> Less m n -> Span ;
+
+

+

+Exercise. Write an abstract and concrete syntax with the +concepts of this section, and experiment with it in GF. +

+

+Exercise. Define the notions of "even" and "odd" in terms +of proof objects. Hint. You need one function for proving +that 0 is even, and two other functions for propagating the +properties. +

+ +

Proof-carrying documents

+

+Another possible application of proof objects is proof-carrying documents: +to be semantically well-formed, the abstract syntax of a document must contain a proof +of some property, although the proof is not shown in the concrete document. +Think, for instance, of small documents describing flight connections: +

+

+To fly from Gothenburg to Prague, first take LH3043 to Frankfurt, then OK0537 to Prague. +

+

+The well-formedness of this text is partly expressible by dependent typing: +

+
+    cat
+      City ;
+      Flight City City ;
+    fun
+      Gothenburg, Frankfurt, Prague : City ;
+      LH3043 : Flight Gothenburg Frankfurt ;
+      OK0537 : Flight Frankfurt Prague ;
+
+

+This rules out texts saying take OK0537 from Gothenburg to Prague. +However, there is a +further condition saying that it must be possible to +change from LH3043 to OK0537 in Frankfurt. +This can be modelled as a proof object of a suitable type, +which is required by the constructor +that connects flights. +

+
+    cat
+      IsPossible (x,y,z : City)(Flight x y)(Flight y z) ;
+    fun
+      Connect : (x,y,z : City) -> 
+        (u : Flight x y) -> (v : Flight y z) -> 
+          IsPossible x y z u v -> Flight x z ;
+
+

+ +

Restricted polymorphism

+

+In the first version of the smart house grammar Smart, +all Actions were either of +

+
    +
  • monomorphic: defined for one Kind +
  • polymorphic: defined for all Kinds +
+ +

+To make this scale up for new Kinds, we can refine this to +restricted polymorphism: defined for Kinds of a certain class +

+

+The notion of class can be expressed in abstract syntax +by using the Curry-Howard isomorphism as follows: +

+
    +
  • a class is a predicate of Kinds --- i.e. a type depending of Kinds +
  • a Kind is in a class if there is a proof object of this type +
+ +

+Here is an example with switching and dimming. The classes are called +switchable and dimmable. +

+
+  cat
+    Switchable Kind ;
+    Dimmable   Kind ;
+  fun
+    switchable_light : Switchable light ;
+    switchable_fan   : Switchable fan ;
+    dimmable_light   : Dimmable light ;
+  
+    switchOn : (k : Kind) -> Switchable k -> Action k ;
+    dim      : (k : Kind) -> Dimmable k -> Action k ;
+
+

+One advantage of this formalization is that classes for new +actions can be added incrementally. +

+

+Exercise. Write a new version of the Smart grammar with +classes, and test it in GF. +

+

+Exercise. Add some actions, kinds, and classes to the grammar. +Try to port the grammar to a new language. You will probably find +out that restricted polymorphism works differently in different languages. +For instance, in Finnish not only doors but also TVs and radios +can be "opened", which means switching them on. +

+ +

Variable bindings

+

+ +

+

+Mathematical notation and programming languages have +expressions that bind variables. For instance, +a universally quantifier proposition +

+
+    (All x)B(x)
+
+

+consists of the binding (All x) of the variable x, +and the body B(x), where the variable x can have +bound occurrences. +

+

+Variable bindings appear in informal mathematical language as well, for +instance, +

+
+    for all x, x is equal to x
+  
+    the function that for any numbers x and y returns the maximum of x+y
+    and x*y
+  
+    Let x be a natural number. Assume that x is even. Then x + 3 is odd.
+
+

+In type theory, variable-binding expression forms can be formalized +as functions that take functions as arguments. The universal +quantifier is defined +

+
+    fun All : (Ind -> Prop) -> Prop
+
+

+where Ind is the type of individuals and Prop, +the type of propositions. If we have, for instance, the equality predicate +

+
+    fun Eq : Ind -> Ind -> Prop
+
+

+we may form the tree +

+
+    All (\x -> Eq x x)
+
+

+which corresponds to the ordinary notation +

+
+    (All x)(x = x).
+
+

+An abstract syntax where trees have functions as arguments, as in +the two examples above, has turned out to be precisely the right +thing for the semantics and computer implementation of +variable-binding expressions. The advantage lies in the fact that +only one variable-binding expression form is needed, the lambda abstract +\x -> b, and all other bindings can be reduced to it. +This makes it easier to implement mathematical theories and reason +about them, since variable binding is tricky to implement and +to reason about. The idea of using functions as arguments of +syntactic constructors is known as higher-order abstract syntax. +

+

+The question now arises: how to define linearization rules +for variable-binding expressions? +Let us first consider universal quantification, +

+
+    fun All : (Ind -> Prop) -> Prop
+
+

+In GF, we write +

+
+    lin All B = {s = "(" ++ "All" ++ B.$0 ++ ")" ++ B.s}
+
+

+to obtain the form shown above. +This linearization rule brings in a new GF concept --- the $0 +field of B containing a bound variable symbol. +The general rule is that, if an argument type of a function is +itself a function type A -> C, the linearization type of +this argument is the linearization type of C +together with a new field $0 : Str. In the linearization rule +for All, the argument B thus has the linearization +type +

+
+    {$0 : Str ; s : Str},
+
+

+since the linearization type of Prop is +

+
+    {s : Str}
+
+

+In other words, the linearization of a function +consists of a linearization of the body together with a +field for a linearization of the bound variable. +Those familiar with type theory or lambda calculus +should notice that GF requires trees to be in +eta-expanded form in order for this to make sense: +for any function of type +

+
+    A -> B
+
+

+an eta-expanded syntax tree has the form +

+
+    \x -> b
+
+

+where b : B under the assumption x : A. +It is in this form that an expression can be analysed +as having a bound variable and a body, which can be put into +a linearization record. +

+

+Given the linearization rule +

+
+    lin Eq a b = {s = "(" ++ a.s ++ "=" ++ b.s ++ ")"}
+
+

+the linearization of +

+
+    \x -> Eq x x
+
+

+is the record +

+
+    {$0 = "x", s = ["( x = x )"]}
+
+

+Thus we can compute the linearization of the formula, +

+
+    All (\x -> Eq x x)  --> {s = "[( All x ) ( x = x )]"}.
+
+

+But how did we get the linearization of the variable x +into the string "x"? GF grammars have no rules for +this: it is just hard-wired in GF that variable symbols are +linearized into the same strings that represent them in +the print-out of the abstract syntax. +

+

+To be able to parse variable symbols, however, GF needs to know what +to look for (instead of e.g. trying to parse any +string as a variable). What strings are parsed as variable symbols +is defined in the lexical analysis part of GF parsing +

+
+    > p -cat=Prop -lexer=codevars "(All x)(x = x)"
+    All (\x -> Eq x x)
+
+

+(see more details on lexers here). If several variables are bound in the +same argument, the labels are $0, $1, $2, etc. +

+

+Exercise. Write an abstract syntax of the whole +predicate calculus, with the +connectives "and", "or", "implies", and "not", and the +quantifiers "exists" and "for all". Use higher-order functions +to guarantee that unbounded variables do not occur. +

+

+Exercise. Write a concrete syntax for your favourite +notation of predicate calculus. Use Latex as target language +if you want nice output. You can also try producing boolean +expressions of some programming language. Use as many parenthesis as you need to +guarantee non-ambiguity. +

+ +

Semantic definitions

+

+ +

+

+Just like any functional programming language, abstract syntax in +GF has declarations of functions, telling what the type of a function is. +But we have not yet shown how to compute +these functions: all we can do is provide them with arguments +and linearize the resulting terms. +Since our main interest is the well-formedness of expressions, +this has not yet bothered +us very much. As we will see, however, computation does play a role +even in the well-formedness of expressions when dependent types are +present. +

+

+GF has a form of judgement for semantic definitions, +marked by the key word def. At its simplest, it is just +the definition of one constant, e.g. +

+
+    fun one : Nat ;
+    def one = Succ Zero ;
+
+

+Notice a def definition can only be given to names declared by +fun judgements in the same module; it is not possible to define +an inherited name. +

+

+We can also define a function with arguments, +

+
+    fun twice : Nat -> Nat ;
+    def twice x = plus x x ;
+
+

+which is still a special case of the most general notion of +definition, that of a group of pattern equations: +

+
+    fun plus : Nat -> Nat -> Nat ;
+    def 
+      plus x Zero = x ;
+      plus x (Succ y) = Succ (Sum x y) ;
+
+

+To compute a term is, as in functional programming languages, +simply to follow a chain of reductions until no definition +can be applied. For instance, we compute +

+
+    Sum one one -->
+    Sum (Succ Zero) (Succ Zero) -->
+    Succ (sum (Succ Zero) Zero) -->
+    Succ (Succ Zero)
+
+

+Computation in GF is performed with the pt command and the +compute transformation, e.g. +

+
+    > p -tr "1 + 1" | pt -transform=compute -tr | l
+    sum one one
+    Succ (Succ Zero)
+    s(s(0))
+
+

+

+The def definitions of a grammar induce a notion of +definitional equality among trees: two trees are +definitionally equal if they compute into the same tree. +Thus, trivially, all trees in a chain of computation +(such as the one above) are definitionally equal to each other. +In general, there can be infinitely many definitionally equal trees. +

+

+An important property of definitional equality is that it is +extensional, i.e. has to do with the sameness of semantic value. +Linearization, on the other hand, is an intensional operation, +i.e. has to do with the sameness of expression. This means that +def definitions are not evaluated as linearization steps. +Intensionality is a crucial property of linearization, since we want +to use it for things like tracing a chain of evaluation. +For instance, each of the steps of the computation above +has a different linearization into standard arithmetic notation: +

+
+    1 + 1
+    s(0) + s(0)
+    s(s(0) + 0)
+    s(s(0))
+
+

+In most programming languages, the operations that can be performed on +expressions are extensional, i.e. give equal values to equal arguments. +But GF has both extensional and intensional operations. +Type checking is extensional: +in the type theory with dependent types, types may depend on terms, +and types depending on definitionally equal terms are +equal types. For instance, +

+
+    Less Zero one
+    Less Zero (Succ Zero))
+
+

+are equal types. Hence, any tree that type checks as a proof that +1 is odd also type checks as a proof that the successor of 0 is odd. +(Recall, in this connection, that the +arguments a category depends on never play any role +in the linearization of trees of that category, +nor in the definition of the linearization type.) +

+

+When pattern matching is performed with def equations, it is +crucial to distinguish between constructors and other functions +(cf. here on pattern matching in concrete syntax). +GF has a judgement form data to tell that a category has +certain functions as constructors: +

+
+    data Nat = Succ | Zero ;
+
+

+Unlike in Haskell and ML, new constructors can be added to +a type with new data judgements. The type signatures of constructors +are given separately, in ordinary fun judgements. +One can also write directly +

+
+    data Succ : Nat -> Nat ;
+
+

+which is syntactic sugar for the pair of judgements +

+
+    fun Succ : Nat -> Nat ;
+    data Nat = Succ ;
+
+

+If we did not mark Zero as data, the definition +

+
+    fun isZero : Nat -> Bool ;
+    def isZero Zero = True ;
+    def isZero _  = False ;
+
+

+would return True for all arguments, because the pattern Zero +would be treated as a variable and it would hence match all values! +This is a common pitfall in GF. +

+

+Exercise. Implement an interpreter of a small functional programming +language with natural numbers, lists, pairs, lambdas, etc. Use higher-order +abstract syntax with semantic definitions. As onject language, use +your favourite programming language. +

+ +

Summary of GF language features

+ +

Judgements

+

+We have generalized the cat judgement form and introduced two new forms +for abstract syntax: +

+ + + + + + + + + + + + + + + + + +
formreading
cat C GC is a category in context G
def f P1 ... Pn = tfunction f applied to P1...Pn has value t
data C = C1 | ... | Cncategory C has constructors C1...Cn
+ +

+

+The context in the cat judgement has the form +

+
+    (x1 : T1) ... (xn : Tn)
+
+

+where the types T1 ... Tn may be increasingly dependent. To form a +type, C must be equipped with arguments of each type in the +context, satisfying the dependencies. As syntactic sugar, we have +

+
+    T G  ===  (x : T) G 
+
+

+if x does not occur in G. The linearization type definition of a +category does not mention the context. +

+

+In def judgements, the arguments P1...Pn can be constructor and +variable patterns as well as wild cards, and the binding and +evaluation rules are the same as here. +

+

+A data judgement states that the names on the right-hand side are constructors +of the category on the left-hand side. The precise types of the constructors are +given in the fun judgements introducing them; the value type of a constructor +of C must be of the form C a1 ... am. As syntactic sugar, +

+
+    data f : A1 ... An -> C a1 ... am  ===   
+    fun f : A1 ... An -> C a1 ... am  ; data C = f ;
+
+

+ +

Dependent function types

+

+A dependent function type has the form +

+
+    (x : A) -> B
+
+

+where B depends on a variable x of type A. We have the +following syntactic sugar: +

+
+    (x,y : A) -> B  ===  (x : A) -> (y : A) -> B
+    
+    (_ : A) -> B    ===  (x : A) -> B  if B does not depend on x
+  
+    A -> B          ===  (_ : A) -> B
+
+

+A fun function in abstract syntax may have function types as +argument types. This is called higher-order abstract syntax. +The linearization of an argument +

+
+    \z0, ..., zn -> b : (x0 : A1) -> ... -> (xn : An) -> B
+
+

+if formed from the linearization of b* of b by adding +fields that hold the variable symbols: +

+
+    b* ** {$0 = "z0" ; ... ; $n = "zn"}
+
+

+If an argument function is itself a higher-order function, its +bound variables cannot be reached in linearization. Thus, in a sense, +the higher-order abstract syntax of GF is just second-orde abstract syntax. +

+

+A syntax tree is a well-typed term in beta-eta normal form, which +means that +

+
    +
  • its type is a basic type, i.e. it is not a partial application; +
  • its arguments are in eta normal form, i.e. either full applications or + lambda abstractions with bodies that are full applications; +
  • it has no beta redexes, i.e. applications of abstractions. +
+ +

+Terms that are not in this form may occur as arguments of dependent types +and in def judgements, but they cannot be linearized. +

+ +

Grammars of formal languages

+

+ +

+

+In this chapter, we will write a grammar for arithmetic expressions as known +from school mathematics and many programming languages. We will see how to +define precedences in GF, how to include built-in integers in grammars, and +how to deal with spaces between tokens in desired ways. As an alternative concrete +syntax, we will generate code for a JVM-like stack machine. We will conclude +by extending the language with variable declarations and assignments, which +are handled in a type-safe way by using higher-order abstract syntax. +

+

+To write grammars for formal languages is usually less challenging than for +natural languages. There are standard tools for this task, such as the YACC +family of parser generators. Using GF would be overkill for many projects, +and come with a penalty in efficiency. However, it is still worth while to +look at this task. A typical application of GF are natural-language interfaces +to formal systems: in such applications, the translation between natural and +formal language can be defined as a multilingual grammar. The use of higher-order +abstract syntax, together with dependent types, provides a way to define a +complete compiler in GF. +

+ +

Arithmetic expressions

+ +

Abstract syntax

+

+We want to write a grammar for what is usually called expressions +in programming languages. The expressions are built from integers by +the binary operations of addition, subtraction, multiplication, and +division. The abstract syntax is easy to write. We call it Calculator, +since it can be used as the basis of a calculator. +

+
+    abstract Calculator = {
+  
+    cat Exp ;
+  
+    fun
+      EPlus, EMinus, ETimes, EDiv : Exp -> Exp -> Exp ;
+      EInt : Int -> Exp ;
+    }
+
+

+Notice the use of the category Int. It is a built-in category of +integers. Its syntax trees are denoted by integer literals, which are +sequences of digits. For instance, +

+
+    5457455814608954681 : Int
+
+

+These are the only objects of type Int: +grammars are not allowed to declare functions with Int as value type. +

+ +

Concrete syntax: a simple approach

+

+Arithmetic expressions should be unambiguous. If we write +

+
+    2 + 3 * 4
+
+

+it should be parsed as one, but not both, of +

+
+    EPlus (EInt 2) (ETimes (EInt 3) (EInt 4))
+    ETimes (EPlus (EInt 2) (EInt 3)) (EInt 4)
+
+

+Under normal conventions, the former is chosen, because +multiplication has higher precedence than addition. +If we want to express the latter tree, we have to use +parentheses: +

+
+    (2 + 3) * 4
+
+

+However, it is not completely trivial to decide when to use +parentheses and when not. We will therefore begin with a +concrete syntax that always uses parentheses around binary +operator applications. +

+
+    concrete CalculatorP of Calculator = {
+  
+    lincat 
+      Exp = SS ;
+    lin
+      EPlus  = infix "+" ;
+      EMinus = infix "-" ;
+      ETimes = infix "*" ;
+      EDiv   = infix "/" ;
+      EInt i = i ;
+  
+    oper
+      infix : Str -> SS -> SS -> SS = \f,x,y -> 
+        ss ("(" ++ x.s ++ f ++ y.s ++ ")") ;
+    }
+
+

+Now we will obtain +

+
+    > linearize EPlus (EInt 2) (ETimes (EInt 3) (EInt 4))
+    ( 2 + ( 3 * 4 ) )
+
+

+The first problem, even more urgent than superfluous parentheses, is +to get rid of superfluous spaces and to recognize integer literals +in the parser. +

+ +

Lexing and unlexing

+

+ +

+

+The input of parsing in GF is not just a string, but a list of +tokens. By default, a list of tokens is obtained from a string +by analysing it into words, which means chunks separated by +spaces. Thus for instance +

+
+    "(12 + (3 * 4))"
+
+

+is split into the tokens +

+
+    "(12", "+", "(3". "*". "4))"
+
+

+The parser then tries to find each of these tokens among the terminals +of the grammar, i.e. among the strings that can appear in linearizations. +In our example, only the tokens "+" and "*" can be found, and +parsing therefore fails. +

+

+The proper way to split the above string into tokens would be +

+
+    "(", "12", "+", "(", "3", "*", "4", ")", ")"
+
+

+Moreover, the tokens "12", "3", and "4" should not be sought +among the terminals in the grammar, but treated as integer tokens, which +are defined outside the grammar. Since GF aims to be fully general, such +conventions are not built in: it must be possible for a grammar to have +tokens such as "12" and "12)". Therefore, GF has a way to select +a lexer, a function that splits strings into tokens and classifies +them into terminals, literalts, etc. +

+

+A lexer can be given as a flag to the parsing command: +

+
+    > parse -cat=Exp -lexer=codelit "(2 + (3 * 4))"
+    EPlus (EInt 2) (ETimes (EInt 3) (EInt 4))
+
+

+Since the lexer is usually a part of the language specification, it +makes sense to put it in the concrete syntax by using the judgement +

+
+    flags lexer = codelit ;
+
+

+The problem of getting correct spacing after linearization is likewise solved +by an unlexer: +

+
+    > l -unlexer=code EPlus (EInt 2) (ETimes (EInt 3) (EInt 4))
+    (2 + (3 * 4))
+
+

+Also this flag is usually put into the concrete syntax file. +

+

+The lexers and unlexers that are available in the GF system can be +seen by +

+
+    > help -lexer
+    > help -unlexer
+
+

+A table of the most common lexers and unlexers is given in the Summary +section 7.8. +

+ +

Precedence and fixity

+

+ +

+

+Here is a summary of the usual +precedence rules in mathematics and programming languages: +

+
    +
  • Integer constants and expressions in parentheses have the highest precedence. +
  • Multiplication and division have equal precedence, lower than the highest + but higher than addition and subtraction, which are again equal. +
  • All the four binary operations are left-associative, which means that + e.g. 1 + 2 + 3 means the same as (1 + 2) + 3. +
+ +

+One way of dealing with precedences in compiler books is by dividing expressions +into three categories: +

+
    +
  • expressions: addition and subtraction +
  • terms: multiplication and division +
  • factors: constants and expressions in parentheses +
+ +

+The context-free grammar, also taking care of associativity, is the following: +

+
+    Exp  ::= Exp  "+" Term | Exp  "-" Term | Term ;
+    Term ::= Term "*" Fact | Term "/" Fact | Fact ;
+    Fact ::= Int | "(" Exp ")" ;
+
+

+A compiler, however, does not want to make a semantic distinction between the +three categories. Nor does it want to build syntax trees with the +coercions that enable the use of a higher level expressions on a lower, and +encode the use of parentheses. In compiler tools such as YACC, building abstract +syntax trees is performed as a semantic action. For instance, if the parser +recognizes an expression in parentheses, the action is to return only the +expression, without encoding the parentheses. +

+

+In GF, semantic actions could be encoded by using def definitions introduced +here. But there is a more straightforward way of thinking about +precedences: we introduce a parameter for precedence, and treat it as +an inherent feature of expressions: +

+
+    oper
+      param Prec = Ints 2 ;
+      TermPrec : Type = {s : Str ; p : Prec} ;
+  
+      mkPrec : Prec -> Str -> TermPrec = \p,s -> {s = s ; p = p} ;
+  
+    lincat 
+      Exp = TermPrec ;
+
+

+This example shows another way to use built-in integers in GF: +the type Ints 2 is a parameter type, whose values are the integers +0,1,2. These are the three precedence levels we need. The main idea +is to compare the inherent precedence of an expression with the context +in which it is used. If the precedence is higher than or equal to +the expected, then +no parentheses are needed. Otherwise they are. We encode this rule in +the operation +

+
+    oper usePrec : TermPrec -> Prec -> Str = \x,p ->
+      case lessPrec x.p p of {
+        True  => "(" x.s ")" ;
+        False => x.s
+      } ;
+
+

+With this operation, we can build another one, that can be used for +defining left-associative infix expressions: +

+
+    infixl : Prec -> Str -> (_,_ : TermPrec) -> TermPrec = \p,f,x,y ->
+      mkPrec p (usePrec x p ++ f ++ usePrec y (nextPrec p)) ;
+
+

+Constant-like expressions (the highest level) can be built simply by +

+
+    constant : Str -> TermPrec = mkPrec 2 ;
+
+

+All these operations can be found in the library module lib/prelude/Formal, +so we don't have to define them in our own code. Also the auxiliary operations +nextPrec and lessPrec used in their definitions are defined there. +The library has 5 levels instead of 3. +

+

+Now we can express the whole concrete syntax of Calculator compactly: +

+
+    concrete CalculatorC of Calculator = open Formal, Prelude in {
+  
+    flags lexer = codelit ; unlexer = code ; startcat = Exp ;
+  
+    lincat Exp = TermPrec ;
+  
+    lin
+      EPlus  = infixl 0 "+" ;
+      EMinus = infixl 0 "-" ;
+      ETimes = infixl 1 "*" ;
+      EDiv   = infixl 1 "/" ;
+      EInt i = constant i.s ;
+    }
+
+

+Let us just take one more look at the operation usePrec, which decides whether +to put parentheses around a term or not. The case where parentheses are not needed +around a string was defined as the string itself. +However, this would imply that superfluous parentheses +are never correct. A more liberal grammar is obtained by using the operation +

+
+    parenthOpt : Str -> Str = \s -> variants {s ; "(" ++ s ++ ")"} ;
+
+

+which is actually used in the Formal library. +But even in this way, we can only allow one pair of superfluous parentheses. +Thus the parameter-based grammar has not quite reached the goal +of implementing the same language as the expression-term-factor grammar. +But it has the advantage of eliminating precedence distinctions from the +abstract syntax. +

+

+Exercise. Define non-associative and right-associative infix operations +analogous to infixl. +

+

+Exercise. Add a constructor that puts parentheses around expressions +to raise their precedence, but that is eliminated by a def definition. +Test parsing with and without a pipe to pt -transform=compute. +

+ +

Code generation as linearization

+

+The classical use of grammars of programming languages is in compilers, +which translate one language into another. Typically the source language of +a compiler is a high-level language and the target language is a machine +language. The hub of a compiler is abstract syntax: the front end of +the compiler parses source language strings into abstract syntax trees, and +the back end linearizes these trees into the target language. This processing +model is of course what GF uses for natural language translation; the main +difference is that, in GF, the compiler could run in the opposite direction as +well, that is, function as a decompiler. (In full-size compilers, the +abstract syntax is also transformed by several layers of semantic analysis +and optimizations, before the target code is generated; this can destroy +reversibility and hence decompilation.) +

+

+More for the sake of illustration +than as a serious compiler, let us write a concrete +syntax of Calculator that generates machine code similar to JVM (Java Virtual +Machine). JVM is a so-called stack machine, whose code follows the +postfix notation, also known as reverse Polish notation. Thus the +expression +

+
+    2 + 3 * 4
+
+

+is translated to +

+
+    iconst 2 : iconst 3 ; iconst 4 ; imul ; iadd
+
+

+The linearization rules are not difficult to give: +

+
+    lin
+      EPlus  = postfix "iadd" ;
+      EMinus = postfix "isub" ;
+      ETimes = postfix "imul" ;
+      EDiv   = postfix "idiv" ;
+      EInt i = ss ("iconst" ++ i.s) ;
+    oper
+      postfix : Str -> SS -> SS -> SS = \op,x,y -> 
+        ss (x.s ++ ";" ++ y.s ++ ";" ++ op) ;
+
+

+ +

Speaking aloud arithmetic expressions

+

+Natural languages have sometimes difficulties in expressing mathematical +formulas unambiguously, because they have no universal device of parentheses. +For arithmetic formulas, a solution exists: +

+
+    2 + 3 * 4
+
+

+can be expressed +

+
+    the sum of 2 and the product of 3 and 4
+
+

+However, this format is very verbose and unnatural, and becomes +impossible to understand when the complexity of expressions grows. +Fortunately, spoken language +has a very nice way of using pauses for disambiguation. This device was +introduced by Torbjörn Lager (personal communication, 2003) +as an input mechanism to a calculator dialogue +system; it seems to correspond very closely to how we actually speak when we +want to communicate arithmetic expressions. Another application would be as +a part of a programming assistant that reads aloud code. +

+

+The idea is that, after every completed operation, there is a pause. Try this +by speaking aloud the following lines, making a pause instead of pronouncing the +word PAUSE: +

+
+    2 plus 3 times 4 PAUSE
+    2 plus 3 PAUSE times 4 PAUSE
+
+

+A grammar implementing this convention is again simple to write: +

+
+    lin
+      EPlus  = infix "plus" ;
+      EMinus = infix "minus" ;
+      ETimes = infix "times" ;
+      EDiv   = infix ["divided by"] ;
+      EInt i = i ;
+    oper
+      infix : Str -> SS -> SS -> SS = \op,x,y -> 
+        ss (x.s ++ op ++ y.s ++ "PAUSE") ;
+
+

+Intuitively, a pause is taken to give the hearer time to compute an +intermediate result. +

+

+Exercise. Is the pause-based grammar unambiguous? Test with random examples! +

+ +

Programs with variables

+

+A useful extension of arithmetic expressions is a straight code programming +language. The programs of this language are assignments of the form x = exp, +which assign expressions to variables. Expressions can moreover contain variables +that have been given values in previous assignments. +

+

+In this language, we use two new categories: programs and variables. +A program is a sequence of assignments, where a variable is given a value. +Logically, we want to distinguish initializations from other assignments: +these are the assignments where a variable is given a value for the first time. +Just like in C-like languages, +we prefix an initializing assignment with the type of the variable. +Here is an example of a piece of code written in the language: +

+
+    int x = 2 + 3 ;  
+    int y = x + 1 ; 
+    x = x + 9 * y ;
+
+

+We define programs by the following constructors: +

+
+    fun
+      PEmpty : Prog ;
+      PInit  : Exp -> (Var -> Prog) -> Prog ;
+      PAss   : Var -> Exp  -> Prog  -> Prog ;
+
+

+The interesting constructor is PInit, which uses +higher-order abstract syntax for making the initialized variable available in +the continuation of the program. The abstract syntax tree for the above code +is +

+
+    PInit (EPlus (EInt 2) (EInt 3)) (\x -> 
+      PInit (EPlus (EVar x) (EInt 1)) (\y -> 
+        PAss x (EPlus (EVar x) (ETimes (EInt 9) (EVar y))) 
+          PEmpty))
+
+

+Since we want to prevent the use of uninitialized variables in programs, we +don't give any constructors for Var! We just have a rule for using variables +as expressions: +

+
+    fun EVar : Var -> Exp ;
+
+

+The rest of the grammar is just the same as for arithmetic expressions +here. The best way to implement it is perhaps by writing a +module that extends the expression module. The most natural start category +of the extension is Prog. +

+

+Exercise. Extend the straight-code language to expressions of type float. +To guarantee type safety, you can define a category Typ of types, and +make Exp and Var dependent on Typ. Basic floating point expressions +can be formed from literal of the built-in GF type Float. The arithmetic +operations should be made polymorphic (as here). +

+ +

The concrete syntax of assignments

+

+We can define a C-like concrete syntax by using GF's $ variables, as explained +here. +

+

+In a JVM-like syntax, we need two more instructions: iload x, which +loads (pushes on the stack) the value of the variable x, and istore x, +which stores the value of the currently topmost expression in the variable x. +Thus the code for the example in the previous section is +

+
+    iconst 2 ; iconst 3 ; iadd ; istore x ;
+    iload x ; iconst 1 ; iadd ; istore y ;
+    iload x ; iconst 9 ; iload y ; imul ; iadd ; istore x ;
+
+

+Those familiar with JVM will notice that we are using symbolic addresses, i.e. +variable names instead of integer offsets in the memory. Neither real JVM nor +our variant makes any distinction between the initialization and reassignment +of a variable. +

+

+Exercise. Finish the implementation of the +C-to-JVM compiler by extending the expression modules +to straight code programs. +

+

+Exercise. If you made the exercise of adding floating point numbers to +the language, you can now cash out the main advantage of type checking +for code generation: selecting type-correct JVM instructions. The floating +point instructions are precisely the same as the integer one, except that +the prefix is f instead of i, and that fconst takes floating +point literals as arguments. +

+ +

A liberal syntax of variables

+

+In many applications, the task of GF is just linearization and parsing; +keeping track of bound variables and other semantic constraints is +the task of other parts of the program. For instance, if we want to +write a natural language interface that reads aloud C code, we can +quite as well use a context-free grammar of C, and leave it to the C +compiler to check that variables make sense. In such a program, we may +want to treat variables as Strings, i.e. to have a constructor +

+
+    fun VString : String -> Var ;
+
+

+The built-in category String has as its values string literals, +which are strings in double quotes. The lexer and unlexer codelit +restore and remove the quotes; when the lexer finds a token that is +neither a terminal in the grammar nor an integer literal, it sends +it to the parser as a string literal. +

+

+Exercise. Write a grammar for straight code without higher-order +abstract syntax. +

+

+Exercise. Extend the liberal straight code grammar to while loops and +some other program constructs, and investigate if you can build a reasonable spoken +language generator for this fragment. +

+ +

Conclusion

+

+Since formal languages are syntactically simpler than natural languages, it +is no wonder that their grammars can be defined in GF. Some thought is needed +for dealing with precedences and spacing, but much of it is encoded in GF's +libraries and built-in lexers and unlexers. If the sole purpose of a grammar +is to implement a programming language, then the BNF Converter tool +(BNFC) is more appropriate than GF: +

+www.cs.chalmers.se/~markus/BNFC/ +
+BNFC uses standard YACC-like parser tools. GF has flags for printing +grammars in the BNFC format. +

+

+The most common applications of GF grammars of formal languages +are in natural-language interfaces of various kinds. +These systems don't usually need semantic control in GF abstract +syntax. However, the situation can be different if the interface also comprises +an interactive syntax editor, as in the GF-Key system +(Beckert & al. 2006, Burke & Johannisson 2005). +In that system, the editor is used for guiding programmers only to write +type-correct code. +

+

+The technique of continuations in modelling programming languages has recently +been applied to natural language, for processing anaphoric reference, +e.g. pronouns. It may be good to know that GF has the machinery available; +for the time being, however (GF 2.8), dependent types and +higher-order abstract syntax are not supported by the embedded GF implementations +in Haskell and Java. +

+

+Exercise. The book C programming language by Kernighan and Ritchie +(p. 123, 2nd edition, 1988) describes an English-like syntax for pointer and +array declarations, and a C program for translating between English and C. +The following example pair shows all the expression forms needed: +

+
+    char (*(*x[3])())[5]
+  
+    x: array[3] of pointer to function returning 
+    pointer to array[5] of char
+
+

+Implement these translations by a GF grammar. +

+

+Exercise. Design a natural-language interface to Unix command lines. +It should be able to express verbally commands such as +cat, cd, grep, ls, mv, rm, wc and also +pipes built from them. +

+ +

Summary of GF language constructs

+ +

Lexers and unlexers

+

+Lexers are set by the flag lexer and unlexers by the flag unlexer. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
lexerdescription
words(default) tokens are separated by spaces or newlines
literalslike words, but integer and string literals recognized
charseach character is a token
codeprogram code conventions (uses Haskell's lex)
textwith conventions on punctuation and capital letters
codelitlike code, but recognize literals (unknown words as strings)
textlitlike text, but recognize literals (unknown words as strings)
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
unlexerdescription
unwords(default) space-separated token list
textformat as text: punctuation, capitals, paragraph <p>
codeformat as code (spacing, indentation)
textlitlike text, but remove string literal quotes
codelitlike code, but remove string literal quotes
concatremove all spaces
+ +

+ +

Built-in abstract syntax types

+

+There are three built-in types. Their syntax trees are literals of corresponding kinds: +

+
    +
  • Int, with nonnegative integer literals e.g. 987031434 +
  • Float, with nonnegative floating-point literals e.g. 907.219807 +
  • String, with string literals e.g. "foo" +
+ +

+Their linearization type is uniformly {s : Str}. +

+ +

Embedded grammars

+

+ +

+

+GF grammars can be used as parts of programs written in other programming +languages. Haskell and Java. +This facility is based on several components: +

+
    +
  • a portable format for multilingual GF grammars +
  • an interpreter for this format written in the host language +
  • an API that enables reading grammar files and calling the interpreter +
  • a way to manipulate abstract syntax trees in the host language +
+ +

+In this chapter, we will show the basic ways of producing such +embedded grammars and using them in Haskell, Java, and JavaScript programs. +We will build a simple example application in each language: +

+
    +
  • a question-answering system in Haskell +
  • a translator GUI in Java +
  • a multilingual syntax editor in JavaScript +
+ +

+Moreover, we will use how grammar applications can be extended to +spoken language by generating language models for speech recognition +in various standard formats. +

+ +

The portable grammar format

+

+The portable format is called GFCC, "GF Canonical Compiled". A file +of this form can be produced from GF by the command +

+
+    > print_multi -printer=gfcc | write_file FILE.gfcc
+
+

+Files written in this format can also be imported in the GF system, +which recognizes the suffix .gfcc and builds the multilingual +grammar in memory. +

+

+This applies to GF version 3 and upwards. Older GF used a format suffixed +.gfcm. +At the moment of writing, also the Java interpreter still uses the GFCM format. +

+

+GFCC is, in fact, the recommended format in +which final grammar products are distributed, because they +are stripped from superfluous information and can be started and applied +faster than sets of separate modules. +

+

+Application programmers have never any need to read or modify GFCC files. +Also in this sense, they play the same role as machine code in +general-purpose programming. +

+ +

The embedded interpreter and its API

+

+The interpreter is a kind of a miniature GF system, which can parse and +linearize with grammars. But it can only perform a subset of the commands of +the GF system. For instance, it +cannot compile source grammars into the GFCC format; the compiler is the most +heavy-weight component of the GF system, and should not be carried around +in end-user applications. +Since GFCC is much +simpler than source GF, building an interpreter is relatively easy. +Full-scale interpreters currently exist in Haskell and Java, and partial +ones in C++, JavaScript, and Prolog. We will in this chapter focus +on Haskell, Java, and JavaScript. +

+

+Application programmers never need to read or modify the interpreter. +They only need to access it via its API. +

+ +

Embedded GF applications in Haskell

+

+Readers unfamiliar with Haskell, or who just want to program in Java, can safely +skip this section. Everything will be repeated in the corresponding Java +section. However, seeing the Haskell code may still be helpful because +Haskell is in many ways closer to GF than Java is. In particular, recursive +types of syntax trees and pattern matching over them are very similar in +Haskell and GF, +but require a complex encoding with classes and visitors in Java. +

+ +

The EmbedAPI module

+

+The Haskell API contains (among other things) the following types and functions: +

+
+  module EmbedAPI where
+  
+  type MultiGrammar 
+  type Language     
+  type Category     
+  type Tree         
+  
+  file2grammar :: FilePath -> IO MultiGrammar
+  
+  linearize :: MultiGrammar -> Language -> Tree -> String
+  parse     :: MultiGrammar -> Language -> Category -> String -> [Tree]
+  
+  linearizeAll     :: MultiGrammar -> Tree -> [String]
+  linearizeAllLang :: MultiGrammar -> Tree -> [(Language,String)]
+  
+  parseAll     :: MultiGrammar -> Category -> String -> [[Tree]]
+  parseAllLang :: MultiGrammar -> Category -> String -> [(Language,[Tree])]
+  
+  languages  :: MultiGrammar -> [Language]
+  categories :: MultiGrammar -> [Category]
+  startCat   :: MultiGrammar -> Category
+
+

+This is the only module that needs to be imported in the Haskell application. +It is available as a part of the GF distribution, in the file +src/GF/GFCC/API.hs. +

+ +

First application: a translator

+

+Let us first build a stand-alone translator, which can translate +in any multilingual grammar between any languages in the grammar. +The whole code for this translator is here: +

+
+  module Main where
+  
+  import GF.GFCC.API
+  import System (getArgs)
+  
+  main :: IO () 
+  main = do
+    file:_ <- getArgs
+    gr <- file2grammar file
+    interact (translate gr)
+  
+  translate :: MultiGrammar -> String -> String
+  translate gr = case parseAllLang gr (startCat gr) s of
+    (lg,t:_):_ -> unlines [linearize gr l t | l <- languages gr, l /= lg]
+    _ -> "NO PARSE"
+
+

+To run the translator, first compile it by +

+
+    % ghc --make -o trans Translator.hs 
+
+

+Then produce a GFCC file. For instance, the Food grammar set can be +compiled as follows: +

+
+    % gfc --make FoodEng.gf FoodIta.gf
+
+

+This produces the file Food.gfcc (its name comes from the abstract syntax). +

+

+The gfc batch compiler program is available in GF 3 and upwards. +In earlier versions, the appropriate command can be piped to gf: +

+
+    % echo "pm -printer=gfcc | wf Food.gfcc" | gf FoodEng.gf FoodIta.gf
+
+

+Equivalently, the grammars could be read into GF shell and the pm command +issued from there. But the unix command has the advantage that it can +be put into a Makefile to automate the compilation of an application. +

+

+The Haskell library function interact makes the trans program work +like a Unix filter, which reads from standard input and writes to standard +output. Therefore it can be a part of a pipe and read and write files. +The simplest way to translate is to echo input to the program: +

+
+    % echo "this wine is delicious" | ./trans Food.gfcc
+    questo vino è delizioso
+
+

+The result is given in all languages except the input language. +

+ +

A looping translator

+

+If the user wants to translate many expressions in a sequence, it +is cumbersome to have to start the translator over and over again, +because reading the grammar and building the parser always takes +time. The translator of the previous section is easy to modify +to enable this: just change interact in the main function to +loop. It is not a standard Haskell function, so its definition has +to be included: +

+
+  loop :: (String -> String) -> IO ()
+  loop trans = do 
+    s <- getLine
+    if s == "quit" then putStrLn "bye" else do  
+      putStrLn $ trans s
+      loop trans
+
+

+The loop keeps on translating line by line until the input line +is quit. +

+ +

A question-answer system

+

+ +

+

+The next application is also a translator, but it adds a +transfer component to the grammar. Transfer is a function that +takes the input syntax tree into some other syntax tree, which is +then linearized and shown back to the user. The transfer function we +are going to use is one that computes a question into an answer. +The program accepts simple questions about arithmetic and answers +"yes" or "no" in the language in which the question was made: +

+
+    Is 123 prime?
+    No.
+    77 est impair ?
+    Oui.
+
+

+The main change that is needed to the pure translator is to give +the type of translate an extra argument: a transfer function. +

+
+    translate :: (Tree -> Tree) -> MultiGrammar -> String -> String
+
+

+You can think of ordinary translation as a special case where +transfer is the identity function (id in Haskell). +

+

+Also the behaviour of returning the reply in different languages +should be changed so that the reply is returned in the same language. +Here is the complete definition of translate in the new form. +

+
+    translate tr gr = case parseAllLang gr (startCat gr) s of
+      (lg,t:_):_ -> linearize gr lg (tr t)
+      _ -> "NO PARSE"
+
+

+To complete the system, we have to define the transfer function. +So, how can we write a function from from abstract syntax trees +to abstract syntax trees? The embedded API does not make +the constructors of the type Tree available for users. Even if it did, it would +be quite complicated to use the type, and programs would be likely +to produce trees that are ill-typed in GF and therefore cannot +be linearized. +

+ +

Exporting GF datatypes

+

+The way to go in defining transfer is to use GF's tree constructors, that +is, the fun functions, as if they were Haskell's data constructors. +There is enough resemblance between GF and Haskell to make this possible +in most cases. It is even possible in Java, as we shall see later. +

+

+Thus every category of GF is translated into a Haskell datatype, where the +functions producing a value of that category are treated as constructors. +The translation is obtained by using the batch compiler with the command +

+
+    % gfc -haskell Food.gfcc
+
+

+It is also possible to produce the Haskell file together with GFCC, by +

+
+    % gfc --make -haskell FoodEng.gf FoodIta.gf
+
+

+The result is a file named GSyntax.hs, containing a +module named GSyntax. +

+

+In GF before version 3, the same result is obtained from within GF, by the command +

+
+    > print_grammar -printer=gfcc_haskell | write_file GSyntax.hs
+
+

+

+As an example, we take +the grammar we are going to use for queries. The abstract syntax is +

+
+    abstract Math = {
+  
+    flags startcat = Question ;
+  
+    cat Answer ; Question ; Object ;
+  
+    fun 
+      Even   : Object -> Question ;
+      Odd    : Object -> Question ;
+      Prime  : Object -> Question ;
+      Number : Int -> Object ;
+  
+      Yes : Answer ;
+      No  : Answer ;
+    }
+
+

+It is translated to the following system of datatypes: +

+
+  newtype GInt = GInt Integer
+  
+  data GAnswer =
+     GYes 
+   | GNo 
+  
+  data GObject = GNumber GInt 
+  
+  data GQuestion =
+     GPrime GObject 
+   | GOdd GObject 
+   | GEven GObject 
+
+

+All type and constructor names are prefixed with a G to prevent clashes. +

+

+Now it is possible to define functions from and to these datatype, in Haskell. +Haskell's type checker guarantees that the functions are well-typed also with +respect to GF. Here is a question-to-answer function for this language: +

+
+  answer :: GQuestion -> GAnswer
+  answer p = case p of
+    GOdd x   -> test odd x
+    GEven x  -> test even x
+    GPrime x -> test prime x
+  
+  value :: GObject -> Int
+  value e = case e of
+    GNumber (GInt i) -> fromInteger i
+  
+  test :: (Int -> Bool) -> GObject -> GAnswer
+  test f x = if f (value x) then GYes else GNo
+
+

+So it is the function answer that we want to apply as transfer. +The only problem is the type of this function: the parsing and +linearization method of API work with Trees and not +with GQuestions and GAnswers. +

+

+Fortunately the Haskell translation of GF takes care of translating +between trees and the generated datatypes. This is done by using +a class with the required translation methods: +

+
+  class Gf a where 
+    gf :: a -> Tree
+    fg :: Tree -> a
+
+

+The Haskell code generator also generates instances of these classes +for each datatype, for example, +

+
+  instance Gf GQuestion where
+    gf (GEven x1) = DTr [] (AC (CId "Even")) [gf x1]
+    gf (GOdd x1) = DTr [] (AC (CId "Odd")) [gf x1]
+    gf (GPrime x1) = DTr [] (AC (CId "Prime")) [gf x1]
+    fg t =
+      case t of
+        DTr [] (AC (CId "Even")) [x1] -> GEven (fg x1)
+        DTr [] (AC (CId "Odd")) [x1] -> GOdd (fg x1)
+        DTr [] (AC (CId "Prime")) [x1] -> GPrime (fg x1)
+        _ -> error ("no Question " ++ show t)
+
+

+Needless to say, GSyntax is a module that a programmer +never needs to look into, let alone change: it is enough to know that it +contains a systematic encoding and decoding between an abstract syntax +and Haskell datatypes, where +

+
    +
  • all GF names are in Haskell prefixed with G +
  • gf translates from Haskell to GF +
  • fg translates from GF to Haskell +
+ + +

Putting it all together

+

+Here is the complete code for the Haskell module TransferLoop.hs. +

+
+  module Main where
+  
+  import GF.GFCC.API
+  import TransferDef (transfer)
+  
+  main :: IO () 
+  main = do
+    gr <- file2grammar "Math.gfcc"
+    loop (translate transfer gr)
+  
+  loop :: (String -> String) -> IO ()
+  loop trans = do 
+    s <- getLine
+    if s == "quit" then putStrLn "bye" else do  
+      putStrLn $ trans s
+      loop trans
+  
+  translate :: (Tree -> Tree) -> MultiGrammar -> String -> String
+  translate tr gr = case parseAllLang gr (startCat gr) s of
+    (lg,t:_):_ -> linearize gr lg (tr t)
+    _ -> "NO PARSE"
+
+

+This is the Main module, which just needs a function transfer from +TransferDef in order to compile. In the current application, this module +looks as follows: +

+
+  module TransferDef where
+  
+  import GF.GFCC.API (Tree)
+  import GSyntax
+  
+  transfer :: Tree -> Tree
+  transfer = gf . answer . fg
+  
+  answer :: GQuestion -> GAnswer
+  answer p = case p of
+    GOdd x   -> test odd x
+    GEven x  -> test even x
+    GPrime x -> test prime x
+  
+  value :: GObject -> Int
+  value e = case e of
+    GNumber (GInt i) -> fromInteger i
+  
+  test :: (Int -> Bool) -> GObject -> GAnswer
+  test f x = if f (value x) then GYes else GNo
+  
+  prime :: Int -> Bool
+  prime x = elem x primes where
+    primes = sieve [2 .. x]
+    sieve (p:xs) = p : sieve [ n | n <- xs, n `mod` p > 0 ]
+    sieve [] = []
+
+

+This module, in turn, needs GSyntax to compile, and the main module +needs Math.gfcc to run. To automate the production of the system, +we write a Makefile as follows: +

+
+  all:
+          gfc --make -haskell MathEng.gf MathFre.gf
+          ghc --make -o ./math TransferLoop.hs
+          strip math
+
+

+(Notice that the empty segments starting the command lines in a Makefile must be tabs.) +Now we can compile the whole system by just typing +

+
+    make
+
+

+Then you can run it by typing +

+
+    ./math
+
+

+Well --- you will of course need some concrete syntaxes of Math in order +to succeed. We have defined ours by using the resource functor design pattern, +as explained here. +

+

+Just to summarize, the source of the application consists of the following files: +

+
+    Makefile         -- a makefile
+    Math.gf          -- abstract syntax
+    Math???.gf       -- concrete syntaxes
+    TransferDef.hs   -- definition of question-to-answer function
+    TransferLoop.hs  -- Haskell Main module
+
+

+ +

Embedded GF applications in Java

+

+When an API for GFCC in Java is available, +we will write the same applications in Java as +were written in Haskell above. Until then, we will +build another kind of application, which does not require +modification of generated Java code. +

+

+More information on embedded GF grammars in Java can be found in the document +

+
+    www.cs.chalmers.se/~bringert/gf/gf-java.html
+
+

+by Björn Bringert. +

+ +

Translets

+

+A Java system needs many more files than a Haskell system. +To get started, one can fetch the package gfc2java from +

+
+    www.cs.chalmers.se/~bringert/darcs/gfc2java/
+
+

+by using the Darcs version control system as described in the gf-java home page. +

+

+The gfc2java package contains a script build-translet, which can be applied +to any .gfcm file to create a translet, a small translation GUI. Foor the Food +grammars of the third chapter, we first create a file food.gfcm by +

+
+    % echo "pm | wf food.gfcm" | gf FoodEng.gf FoodIta.gf
+
+

+and then run +

+
+    % build_translet food.gfcm
+
+

+The resulting file translate-food.jar can be run with +

+
+    % java -jar translate-food.jar
+
+

+The translet looks like this: +

+

+ +

+ +

Dialogue systems

+

+A question-answer system is a special case of a dialogue system, where the user and +the computer communicate by writing or, even more properly, by speech. The gf-java +homepage provides an example of a most simple dialogue system imaginable, where two +the conversation has just two rules: +

+
    +
  • if the user says here you go, the system says thanks +
  • if the user says thanks, the system says you are welcome +
+ +

+The conversation can be made in both English and Swedish; the user's initiative +decides which language the system replies in. Thus the structure is very similar +to the math program here. The GF and +Java sources of the program can be +found in +

+
+    www.cs.chalmers.se/~bringert/darcs/simpledemo
+
+

+again accessible with the Darcs version control system. +

+ +

Language models for speech recognition

+

+The standard way of using GF in speech recognition is by building +grammar-based language models. To this end, GF comes with compilers +into several formats that are used in speech recognition systems. +One such format is GSL, used in the Nuance speech recognizer. +It is produced from GF simply by printing a grammar with the flag +-printer=gsl. The following example uses the smart house grammar defined +here. +

+
+    > import -conversion=finite SmartEng.gf
+    > print_grammar -printer=gsl
+  
+    ;GSL2.0
+    ; Nuance speech recognition grammar for SmartEng
+    ; Generated by GF
+  
+    .MAIN SmartEng_2
+  
+    SmartEng_0 [("switch" "off") ("switch" "on")]
+    SmartEng_1 ["dim" ("switch" "off")
+                ("switch" "on")]
+    SmartEng_2 [(SmartEng_0 SmartEng_3)
+                (SmartEng_1 SmartEng_4)]
+    SmartEng_3 ("the" SmartEng_5)
+    SmartEng_4 ("the" SmartEng_6)
+    SmartEng_5 "fan"
+    SmartEng_6 "light"
+
+

+Other formats available via the -printer flag include: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatDescription
gslNuance GSL speech recognition grammar
jsgfJava Speech Grammar Format (JSGF)
jsgf_sisr_oldJSGF with semantic tags in SISR WD 20030401 format
srgs_abnfSRGS ABNF format
srgs_xmlSRGS XML format
srgs_xml_probSRGS XML format, with weights
slffinite automaton in the HTK SLF format
slf_subfinite automaton with sub-automata in HTK SLF
+ +

+

+All currently available formats can be seen in gf with help -printer. +

+ +

Dependent types and spoken language models

+

+We have used dependent types to control semantic well-formedness +in grammars. This is important in traditional type theory +applications such as proof assistants, where only mathematically +meaningful formulas should be constructed. But semantic filtering has +also proved important in speech recognition, because it reduces the +ambiguity of the results. +

+

+Now, GSL is a context-free format, so how does it cope with dependent types? +In general, dependent types can give rise to infinitely many basic types +(exercise!), whereas a context-free grammar can by definition only have +finitely many nonterminals. +

+

+This is where the flag -conversion=finite is needed in the import +command. Its effect is to convert a GF grammar with dependent types to +one without, so that each instance of a dependent type is replaced by +an atomic type. This can then be used as a nonterminal in a context-free +grammar. The finite conversion presupposes that every +dependent type has only finitely many instances, which is in fact +the case in the Smart grammar. +

+

+Exercise. If you have access to the Nuance speech recognizer, +test it with GF-generated language models for SmartEng. Do this +both with and without -conversion=finite. +

+

+Exercise. Construct an abstract syntax with infinitely many instances +of dependent types. +

+ +

Statistical language models

+

+An alternative to grammar-based language models are +statistical language models (SLMs). An SLM is +built from a corpus, i.e. a set of utterances. It specifies the +probability of each n-gram, i.e. sequence of n words. The +typical value of n is 2 (bigrams) or 3 (trigrams). +

+

+One advantage of SLMs over grammar-based models is that they are +robust, i.e. they can be used to recognize sequences that would +be out of the grammar or the corpus. Another advantage is that +an SLM can be built "for free" if a corpus is available. +

+

+However, collecting a corpus can require a lot of work, and writing +a grammar can be less demanding, especially with tools such as GF or +Regulus. This advantage of grammars can be combined with robustness +by creating a back-up SLM from a synthesized corpus. This means +simply that the grammar is used for generating such a corpus. +In GF, this can be done with the generate_trees command. +As with grammar-based models, the quality of the SLM is better +if meaningless utterances are excluded from the corpus. Thus +a good way to generate an SLM from a GF grammar is by using +dependent types and filter the results through the type checker: +

+
+    > generate_trees | put_trees -transform=solve | linearize
+
+

+The method of creating statistical language model from corpora synthesized +from GF grammars is applied and evaluated in (Jonson 2006). +

+

+Exercise. Measure the size of the corpus generated from +SmartEng (defined here), with and without type checker filtering. +

+ + + + diff --git a/doc/mytree.png b/doc/mytree.png new file mode 100644 index 0000000000000000000000000000000000000000..fafcc87723d65a4af6fe0842aaae30053fceaf26 GIT binary patch literal 2230 zcmeAS@N?(olHy`uVBq!ia0y~yVAN+|U}R%qW?*1A7R)Egz`&pq;1lBd@Bjbh%a@mz zm)qOh%gf8h$H(vAzkmMx`Stbn_wV0lU|{(F|9`}JF-ryp2F8*gzhDN3XE)Lq7&sg} zT^vIy=DeMIHt4p8Nb7UiXP(PEoFuL#*ytR#KkdMAO-P0#ijRjgsx8rB@9c)$o3mFQ z%Jbf(Z+=(zr+bKkufso(E2Tft3=N1L~8D%)YN z=ES83H(W}H$TV1EA`vFVv-&#ov%59C?|1r#@4mZq&F2;6XWrc}e$evw)QY5oTANwR z{_;M!nUYY#_)7YEx9ayhN%royFS8YEI80|SkuP897QMASdi~SM{?mMy@oYRH2 z@3Jx8D)^s!;PWG|-)HVbA3pQB>fX;#PgJL_=U-#`=fLsn;;d#(mnO+iT_DbMI66$^ z#tPSr(_Bo_#T>bjjtR+ZXLTfYO+VV;`DZ4t0VnIW>8%Z(iW8=ZGO49HM1`?L@Gza* zB+ha;GK?jn$JCg+?R6?+!p3t8bhH_C?n(5dzB(vWb1-6=oX$zHmef-Rg<@w$8o20B zZC0ISp1vU(@G zd!3%rw6rKW?O@QiAk7FZ<7EufK23R9Wy!jsqJojF^9yXO#S`Nzq&VRMS}5#ucr?4@-Me4S^4RD>(68fJ@y%ajK|g2 z%>MJ~kz(*^HPcgVDXiOe{=ZrLC;8JoW7pQR>pG_S=j6|w`l)l?+WI!`q6R^;}duxxSRqNk7ZYNQlz2)B8P@l|`;xBBX#LrAA6%Y-uz0Fkq^hkuo-Bp*X zp381gKED5tb^ZFpxMG#{uifPKTHLUGd3U#l>%0$2*Z*}lm%jeHyF~eu`F(EVq6am# z9s66rIYgVc?P^SO>WLgby~_zVjCk90XJ;GK#6^0brcY1~Tei)wIq|iL1a>NK-Ttk5 zE+BP?oaoeiajteze0_w$Ef<@8@%(vg&i9^11WNpp>CWd@Iwm zv-U%pK}vsk>q7r@4R$W&lYU$iQ`Dt$1RtErmi;FG{UDpO(FTPtmYbGj1Z@)LJ*H;y zA?x%RtD=C|=FM5&2l(1{rB@3X+%jnTv8+1p;-xmzd2jxBD4q1vkuX2;P409}*!>kd z)Oa^FG%w6v;c?&q=i}MibK0UJL_EtjJ$jg;F6CqKY|leUSF_aFU!rcxYn@(isNR!* zD6rdIr}^T;6m@+$ud+qaJGItry#2J{kom9c5&0{`*u{>R|7==hyTN1AWO05~YvVmy zjeE8B&SyOOxoG{=zYAM;gt2|}{jJ9$?OVpR!Euu?@3p(@q`sHF|Gu;<(lEd8evV$} zgl7pau21Dp+2YY+*Zkwz=SN&?cW?cel76&D#ros>KWoBIO_}iKNOP(D**!MQN7b#3 zYr^FIO`N@a{g0IAe`-4RPk}|_RJOxf>^ENQ&rIjJcT|J@#*Oe5k^8%+YFXdd;pnA% znosSc`_j~z2UEVS*rH=RnvPm6KC>w& z;o~ul%{tN%P5P^JX6tWQQn&I|s@evZaFNJqtU5PET&JBCz0s1k@?|R9hG#9$uST@7 z&#t-W`DA4ayZ1#+(X%eiOEaf*r7b!bv~%HsO*?^A~nVfe{xNO8Dajs>~w8R4wHRcX2o=Qq0K2TbQ^PDmVHp_lSg|KED$Lwx_({`>e*M zW7ucK_@*JucYcjZ-qoc2bKkdlUPxfB`nRR{e$jc|vJD}lP+rJ+b6fGkkal+8rG-~K`#MYQenvL_PrJQjKjYqxnO#>N2Xb7C<~3Oq zYB>3NhS~YqzQq}fs|4Lkf3RG#c*U|ocH_C_{#k#PvDvY|&UHASysYNlxk8AJxeRYk zvg}*(;)2^(r9Q0#OA4=~Y5%va^?LoUu~X)@SOa z=H6pI?5i8al#ZmQnxt86k;+h<^_Tx+