From 03479648ad008966d15c7866630fef443f70f4dd Mon Sep 17 00:00:00 2001
From: Krasimir Angelov
+>>> quant = pgf.readExpr("DetQuant IndefArt NumSg")
+>>> e2 = pgf.Expr("DetCN", [quant, e])
+>>> print(e2)
+DetCN (DetQuant IndefArt NumSg) (AdjCN (PositA red_A) (UseN theatre_N))
+
+
+
+using the functions mkApp, mkStr, mkInt, mkFloat and mkMeta:
++Prelude PGF2> let Just quant = readExpr "DetQuant IndefArt NumSg" +Prelude PGF2> let e2 = mkApp "DetCN" [quant, e] +Prelude PGF2> print e2 +DetCN (DetQuant IndefArt NumSg) (AdjCN (PositA red_A) (UseN theatre_N)) ++ + +using the constructor for Expr: +
+Expr quant = Expr.readExpr("DetQuant IndefArt NumSg");
+Expr e2 = new Expr("DetCN", new Expr[] {quant, e});
+System.out.println(e2);
+
+
+
+using the constructor for Expr:
+
+Expr quant = Expr.ReadExpr("DetQuant IndefArt NumSg");
+Expr e2 = new Expr("DetCN", new Expr[] {quant, e});
+Console.WriteLine(e2);
+
+
+
+If the host application needs to do a lot of expression manipulations, +then it is helpful to use a higher-level API to the grammar, +also known as "embedded grammars" in GF. The advantage is that +you can construct and analyze expressions in a more compact way.
+ + +In Python you first have to embed the grammar by calling: +
+>>> gr.embed("App")
+<module 'App' (built-in)>
+
+After that whenever you need the API you should import the module:
++>>> import App ++ +
Now creating new trees is just a matter of calling ordinary Python +functions: +
+>>> print(App.DetCN(quant,e)) +DetCN (DetQuant IndefArt NumSg) (AdjCN (PositA red_A) (UseN house_N)) ++ + + +
In order to access the API you first need to generate +one boilerplate Haskell module with the compiler: +
+$ gf -make -output-format=haskell App.pgf ++This module will expose all functions in the abstract syntax +as data type constructors together with methods for conversion from +a generic expression to Haskell data and vice versa. When you need the API you can just import the module: +
+Prelude PGF2> import App ++ +
Now creating new trees is just a matter of writing ordinary Haskell +code: +
+Prelude PGF2 App> print (gf (GDetCN (GDetQuant GIndefArt GNumSg) (GAdjCN (GPositA Gred_A) (GUseN Ghouse_N)))) ++The only difference is that to the name of every abstract syntax function +the compiler adds a capital 'G' in order to guarantee that there are no conflicts +and that all names are valid names for Haskell data constructors. Here gf is a function +which converts from the data type representation to generic GF expressions. + +
The converse function fg converts an expression to a data type expression. +This is useful for instance if you want to do pattern matching +on the structure of the expression: +
+visit = case fg e2 of + GDetCN quant cn -> do putStrLn "Found DetCN" + visit cn + GAdjCN adj cn -> do putStrLn "Found AdjCN" + visit cn + e -> return () ++ + +
-For more complex analyses you can use the visitor pattern. -In object oriented languages this is just a clumpsy way to do +Analysing expressions is also made easier by using the visitor pattern. +In object oriented languages this is a clumpsy way to do what is called pattern matching in most functional languages. You need to define a class which has one method for each function -in the abstract syntax of the grammar. If the functions is called +in the abstract syntax that you want to handle. If the functions is called f then you need a method called on_f. The method will be called each time when the corresponding function is encountered, and its arguments will be the arguments from the original tree. @@ -589,11 +690,11 @@ we call visit recursively to go deeper into the tree.
-For more complex analyses you can use the visitor pattern. -In object oriented languages this is just a clumpsy way to do +Analysing expressions is also made easier by using the visitor pattern. +In object oriented languages this is a clumpsy way to do what is called pattern matching in most functional languages. You need to define a class which has one method for each function -in the abstract syntax of the grammar. If the functions is called +in the abstract syntax that you want to handle. If the functions is called f then you need a method called on_f. The method will be called each time when the corresponding function is encountered, and its arguments will be the arguments from the original tree. @@ -627,68 +728,6 @@ we call visit recursively to go deeper into the tree.
-Constructing new trees is also easy. You can either use -readExpr to read trees from strings, or you can -construct new trees from existing pieces. This is possible by - -using the constructor for pgf.Expr: -
->>> quant = pgf.readExpr("DetQuant IndefArt NumSg")
->>> e2 = pgf.Expr("DetCN", [quant, e])
->>> print(e2)
-DetCN (DetQuant IndefArt NumSg) (AdjCN (PositA red_A) (UseN theatre_N))
-
-
-
-using the functions mkApp, mkStr, mkInt, mkFloat and mkMeta:
--Prelude PGF2> let Just quant = readExpr "DetQuant IndefArt NumSg" -Prelude PGF2> let e2 = mkApp "DetCN" [quant, e] -Prelude PGF2> print e2 -DetCN (DetQuant IndefArt NumSg) (AdjCN (PositA red_A) (UseN theatre_N)) -- - -using the constructor for Expr: -
-Expr quant = Expr.readExpr("DetQuant IndefArt NumSg");
-Expr e2 = new Expr("DetCN", new Expr[] {quant, e});
-System.out.println(e2);
-
-
-
-using the constructor for Expr:
-
-Expr quant = Expr.ReadExpr("DetQuant IndefArt NumSg");
-Expr e2 = new Expr("DetCN", new Expr[] {quant, e});
-Console.WriteLine(e2);
-
-
-
-
-
->>> gr.embed("App")
-<module 'App' (built-in)>
->>> import App
-
-Now creating new trees is just a matter of calling ordinary Python
-functions:
-->>> print(App.DetCN(quant,e)) -DetCN (DetQuant IndefArt NumSg) (AdjCN (PositA red_A) (UseN house_N)) -- -