diff --git a/doc/runtime-api.html b/doc/runtime-api.html index d8759e01b..100fd4ffb 100644 --- a/doc/runtime-api.html +++ b/doc/runtime-api.html @@ -550,83 +550,6 @@ There are also the methods UnAbs, UnInt, UnFloat and
- --For more complex analyses you can use the visitor pattern. -In object oriented languages this is just 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 -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. -If there is no matching method name then the runtime will -call the method default. The following is an example: -
->>> class ExampleVisitor:
- def on_DetCN(self,quant,cn):
- print("Found DetCN")
- cn.visit(self)
-
- def on_AdjCN(self,adj,cn):
- print("Found AdjCN")
- cn.visit(self)
-
- def default(self,e):
- pass
->>> e2.visit(ExampleVisitor())
-Found DetCN
-Found AdjCN
-
-Here we call the method visit from the tree e2 and we give
-it, as parameter, an instance of class ExampleVisitor.
-ExampleVisitor has two methods on_DetCN
-and on_AdjCN which are called when the top function of
-the current tree is DetCN or AdjCN
-correspondingly. In this example we just print a message and
-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 -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 -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. -If there is no matching method name then the runtime will -call the method defaultCase. The following is an example: -
-e2.visit(new Object() {
- public void on_DetCN(Expr quant, Expr cn) {
- System.out.println("found DetCN");
- cn.visit(this);
- }
-
- public void on_AdjCN(Expr adj, Expr cn) {
- System.out.println("found AdjCN");
- cn.visit(this);
- }
-
- public void defaultCase(Expr e) {
- System.out.println("found "+e);
- }
- });
-Found DetCN
-Found AdjCN
-
-Here we call the method visit from the tree e2 and we give
-it, as parameter, an instance of a class with two methods on_DetCN
-and on_AdjCN which are called when the top function of
-the current tree is DetCN or AdjCN
-correspondingly. In this example we just print a message and
-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
@@ -665,28 +588,144 @@ 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 + +
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 () ++ + + + +
+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 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. +If there is no matching method name then the runtime will +call the method default. The following is an example: +
+>>> class ExampleVisitor:
+ def on_DetCN(self,quant,cn):
+ print("Found DetCN")
+ cn.visit(self)
+
+ def on_AdjCN(self,adj,cn):
+ print("Found AdjCN")
+ cn.visit(self)
+
+ def default(self,e):
+ pass
+>>> e2.visit(ExampleVisitor())
+Found DetCN
+Found AdjCN
+
+Here we call the method visit from the tree e2 and we give
+it, as parameter, an instance of class ExampleVisitor.
+ExampleVisitor has two methods on_DetCN
+and on_AdjCN which are called when the top function of
+the current tree is DetCN or AdjCN
+correspondingly. In this example we just print a message and
+we call visit recursively to go deeper into the tree.
+
+
+
++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 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. +If there is no matching method name then the runtime will +call the method defaultCase. The following is an example: +
+e2.visit(new Object() {
+ public void on_DetCN(Expr quant, Expr cn) {
+ System.out.println("found DetCN");
+ cn.visit(this);
+ }
+
+ public void on_AdjCN(Expr adj, Expr cn) {
+ System.out.println("found AdjCN");
+ cn.visit(this);
+ }
+
+ public void defaultCase(Expr e) {
+ System.out.println("found "+e);
+ }
+ });
+Found DetCN
+Found AdjCN
+
+Here we call the method visit from the tree e2 and we give
+it, as parameter, an instance of a class with two methods on_DetCN
+and on_AdjCN which are called when the top function of
+the current tree is DetCN or AdjCN
+correspondingly. In this example we just print a message and
+we call visit recursively to go deeper into the tree.
+