forked from GitHub/gf-core
fixed some tutorial grammars and updated embedded section (JavaScript and web TODO)
This commit is contained in:
@@ -4498,7 +4498,6 @@ the prefix is ``f`` instead of ``i``, and that ``fconst`` takes floating
|
|||||||
point literals as arguments.
|
point literals as arguments.
|
||||||
|
|
||||||
|
|
||||||
%TODO: fix embedded grammars lesson
|
|
||||||
|
|
||||||
#NEW
|
#NEW
|
||||||
|
|
||||||
@@ -4507,10 +4506,10 @@ point literals as arguments.
|
|||||||
#Lchapeight
|
#Lchapeight
|
||||||
|
|
||||||
Goals:
|
Goals:
|
||||||
- use as parts of programs written in other programming Haskell and Java
|
- use grammars as parts of programs written in Haskell and JavaScript
|
||||||
- implement stand-alone question-answering systems and translators based on
|
- implement stand-alone question-answering systems and translators based on
|
||||||
GF grammars
|
GF grammars
|
||||||
- generate language models for speech recognition from grammars
|
- generate language models for speech recognition from GF grammars
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -4519,11 +4518,11 @@ Goals:
|
|||||||
==Functionalities of an embedded grammar format==
|
==Functionalities of an embedded grammar format==
|
||||||
|
|
||||||
GF grammars can be used as parts of programs written in other programming
|
GF grammars can be used as parts of programs written in other programming
|
||||||
languages. Haskell and Java.
|
languages, to be called **host languages**.
|
||||||
This facility is based on several components:
|
This facility is based on several components:
|
||||||
- a portable format for multilingual GF grammars
|
- PGF: a portable format for multilingual GF grammars
|
||||||
- an interpreter for this format written in the host language
|
- a PGF interpreter written in the host language
|
||||||
- an API that enables reading grammar files and calling the interpreter
|
- a library in the host language that enables calling the interpreter
|
||||||
- a way to manipulate abstract syntax trees in the host language
|
- a way to manipulate abstract syntax trees in the host language
|
||||||
|
|
||||||
|
|
||||||
@@ -4535,18 +4534,11 @@ This facility is based on several components:
|
|||||||
|
|
||||||
The portable format is called PGF, "Portable Grammar Format".
|
The portable format is called PGF, "Portable Grammar Format".
|
||||||
|
|
||||||
A file can be produced in GF by the command
|
This format is produced by the GF batch compiler ``gfc``,
|
||||||
```
|
executable from the operative system shell:
|
||||||
> print_grammar | write_file FILE.pgf
|
|
||||||
```
|
|
||||||
There is also a batch compiler, executable from the operative system shell:
|
|
||||||
```
|
```
|
||||||
% gfc --make SOURCE.gf
|
% gfc --make SOURCE.gf
|
||||||
```
|
```
|
||||||
//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.//
|
|
||||||
|
|
||||||
PGF is the recommended format in
|
PGF is the recommended format in
|
||||||
which final grammar products are distributed, because they
|
which final grammar products are distributed, because they
|
||||||
are stripped from superfluous information and can be started and applied
|
are stripped from superfluous information and can be started and applied
|
||||||
@@ -4636,6 +4628,8 @@ The simplest way to translate is to ``echo`` input to the program:
|
|||||||
```
|
```
|
||||||
The result is given in all languages except the input language.
|
The result is given in all languages except the input language.
|
||||||
|
|
||||||
|
%TODO convert the output to UTF8
|
||||||
|
|
||||||
|
|
||||||
#NEW
|
#NEW
|
||||||
|
|
||||||
@@ -4694,27 +4688,14 @@ To reply in the //same// language as the question:
|
|||||||
|
|
||||||
#NEW
|
#NEW
|
||||||
|
|
||||||
===Exporting GF datatypes to Haskell===
|
===Abstract syntax of the query system===
|
||||||
|
|
||||||
To make it easy to define a transfer function, we export the
|
|
||||||
abstract syntax to a system of Haskell datatypes:
|
|
||||||
```
|
|
||||||
% gfc --output-format=haskell Food.gfcc
|
|
||||||
```
|
|
||||||
It is also possible to produce the Haskell file together with GFCC, by
|
|
||||||
```
|
|
||||||
% gfc --make --output-format=haskell FoodEng.gf FoodIta.gf
|
|
||||||
```
|
|
||||||
The result is a file named ``Food.hs``, containing a
|
|
||||||
module named ``Food``.
|
|
||||||
|
|
||||||
|
|
||||||
#NEW
|
|
||||||
|
|
||||||
===Example of exporting GF datatypes===
|
|
||||||
|
|
||||||
Input: abstract syntax judgements
|
Input: abstract syntax judgements
|
||||||
```
|
```
|
||||||
|
abstract Query = {
|
||||||
|
|
||||||
|
flags startcat=Question ;
|
||||||
|
|
||||||
cat
|
cat
|
||||||
Answer ; Question ; Object ;
|
Answer ; Question ; Object ;
|
||||||
|
|
||||||
@@ -4726,10 +4707,33 @@ Input: abstract syntax judgements
|
|||||||
|
|
||||||
Yes : Answer ;
|
Yes : Answer ;
|
||||||
No : Answer ;
|
No : Answer ;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#NEW
|
||||||
|
|
||||||
|
===Exporting GF datatypes to Haskell===
|
||||||
|
|
||||||
|
To make it easy to define a transfer function, we export the
|
||||||
|
abstract syntax to a system of Haskell datatypes:
|
||||||
|
```
|
||||||
|
% gfc --output-format=haskell Query.pgf
|
||||||
|
```
|
||||||
|
It is also possible to produce the Haskell file together with GFCC, by
|
||||||
|
```
|
||||||
|
% gfc --make --output-format=haskell QueryEng.gf
|
||||||
|
```
|
||||||
|
The result is a file named ``Query.hs``, containing a
|
||||||
|
module named ``Query``.
|
||||||
|
|
||||||
|
|
||||||
|
#NEW
|
||||||
|
|
||||||
Output: Haskell definitions
|
Output: Haskell definitions
|
||||||
```
|
```
|
||||||
newtype GInt = GInt Integer
|
module Query where
|
||||||
|
import PGF
|
||||||
|
|
||||||
data GAnswer =
|
data GAnswer =
|
||||||
GYes
|
GYes
|
||||||
@@ -4741,6 +4745,8 @@ data GQuestion =
|
|||||||
GPrime GObject
|
GPrime GObject
|
||||||
| GOdd GObject
|
| GOdd GObject
|
||||||
| GEven GObject
|
| GEven GObject
|
||||||
|
|
||||||
|
newtype GInt = GInt Integer
|
||||||
```
|
```
|
||||||
All type and constructor names are prefixed with a ``G`` to prevent clashes.
|
All type and constructor names are prefixed with a ``G`` to prevent clashes.
|
||||||
|
|
||||||
@@ -4792,8 +4798,8 @@ instance Gf GQuestion where
|
|||||||
```
|
```
|
||||||
For the programmer, it is enougo to know:
|
For the programmer, it is enougo to know:
|
||||||
- all GF names are in Haskell prefixed with ``G``
|
- all GF names are in Haskell prefixed with ``G``
|
||||||
- ``gf`` translates from Haskell to GF
|
- ``gf`` translates from Haskell objects to GF trees
|
||||||
- ``fg`` translates from GF to Haskell
|
- ``fg`` translates from GF trees to Haskell objects
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -4805,7 +4811,7 @@ For the programmer, it is enougo to know:
|
|||||||
module TransferDef where
|
module TransferDef where
|
||||||
|
|
||||||
import PGF (Tree)
|
import PGF (Tree)
|
||||||
import Math -- generated from GF
|
import Query -- generated from GF
|
||||||
|
|
||||||
transfer :: Tree -> Tree
|
transfer :: Tree -> Tree
|
||||||
transfer = gf . answer . fg
|
transfer = gf . answer . fg
|
||||||
@@ -4844,7 +4850,7 @@ import TransferDef (transfer)
|
|||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
gr <- file2grammar "Math.pgf"
|
gr <- readPGF "Query.pgf"
|
||||||
loop (translate transfer gr)
|
loop (translate transfer gr)
|
||||||
|
|
||||||
loop :: (String -> String) -> IO ()
|
loop :: (String -> String) -> IO ()
|
||||||
@@ -4855,7 +4861,7 @@ loop trans = do
|
|||||||
loop trans
|
loop trans
|
||||||
|
|
||||||
translate :: (Tree -> Tree) -> PGF -> String -> String
|
translate :: (Tree -> Tree) -> PGF -> String -> String
|
||||||
translate tr gr = case parseAllLang gr (startCat gr) s of
|
translate tr gr s = case parseAllLang gr (startCat gr) s of
|
||||||
(lg,t:_):_ -> linearize gr lg (tr t)
|
(lg,t:_):_ -> linearize gr lg (tr t)
|
||||||
_ -> "NO PARSE"
|
_ -> "NO PARSE"
|
||||||
```
|
```
|
||||||
@@ -4869,7 +4875,7 @@ translate tr gr = case parseAllLang gr (startCat gr) s of
|
|||||||
To automate the production of the system, we write a ``Makefile`` as follows:
|
To automate the production of the system, we write a ``Makefile`` as follows:
|
||||||
```
|
```
|
||||||
all:
|
all:
|
||||||
gfc --make -haskell MathEng.gf MathFre.gf
|
gfc --make --output-format=haskell QueryEng
|
||||||
ghc --make -o ./math TransferLoop.hs
|
ghc --make -o ./math TransferLoop.hs
|
||||||
strip math
|
strip math
|
||||||
```
|
```
|
||||||
@@ -4891,70 +4897,14 @@ Just to summarize, the source of the application consists of the following files
|
|||||||
TransferLoop.hs -- Haskell Main module
|
TransferLoop.hs -- Haskell Main module
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#NEW
|
#NEW
|
||||||
|
|
||||||
===Translets: embedded translators in Java===
|
TODO: web server applications
|
||||||
|
|
||||||
**NOTICE**. Only for GF 2.9 and older at the moment.
|
|
||||||
|
|
||||||
A Java system needs many more files than a Haskell system.
|
|
||||||
To get started, fetch the package ``gfc2java`` from
|
|
||||||
|
|
||||||
[``www.cs.chalmers.se/~bringert/darcs/gfc2java/`` http://www.cs.chalmers.se/~bringert/darcs/gfc2java/]
|
|
||||||
|
|
||||||
by using the Darcs version control system as described in this 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.
|
|
||||||
|
|
||||||
For the ``Food``
|
|
||||||
grammars of #Rchapthree, 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:
|
|
||||||
|
|
||||||
[food-translet.png]
|
|
||||||
|
|
||||||
|
|
||||||
#NEW
|
#NEW
|
||||||
|
|
||||||
===Dialogue systems in Java===
|
TODO: JavaScript applications
|
||||||
|
|
||||||
**NOTICE**. Only for GF 2.9 and older at the moment.
|
|
||||||
|
|
||||||
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 #Rsecmathprogram.
|
|
||||||
|
|
||||||
|
|
||||||
The GF and Java sources of the program can be
|
|
||||||
found in
|
|
||||||
|
|
||||||
[``www.cs.chalmers.se/~bringert/darcs/simpledemo http://www.cs.chalmers.se/~bringert/darcs/simpledemo``]
|
|
||||||
|
|
||||||
again accessible with the Darcs version control system.
|
|
||||||
|
|
||||||
|
|
||||||
#NEW
|
#NEW
|
||||||
|
|||||||
4
examples/tutorial/embedded/Makefile
Normal file
4
examples/tutorial/embedded/Makefile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
all:
|
||||||
|
gfc --make --output-format=haskell QueryEng.gf
|
||||||
|
ghc --make -o ./math TransferLoop.hs
|
||||||
|
strip math
|
||||||
17
examples/tutorial/embedded/Query.gf
Normal file
17
examples/tutorial/embedded/Query.gf
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
abstract Query = {
|
||||||
|
|
||||||
|
flags startcat=Question ;
|
||||||
|
|
||||||
|
cat
|
||||||
|
Answer ; Question ; Object ;
|
||||||
|
|
||||||
|
fun
|
||||||
|
Even : Object -> Question ;
|
||||||
|
Odd : Object -> Question ;
|
||||||
|
Prime : Object -> Question ;
|
||||||
|
Number : Int -> Object ;
|
||||||
|
|
||||||
|
Yes : Answer ;
|
||||||
|
No : Answer ;
|
||||||
|
}
|
||||||
|
|
||||||
15
examples/tutorial/embedded/QueryEng.gf
Normal file
15
examples/tutorial/embedded/QueryEng.gf
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
concrete QueryEng of Query = {
|
||||||
|
lincat
|
||||||
|
Answer, Question, Object = Str ;
|
||||||
|
|
||||||
|
lin
|
||||||
|
Even x = "is" ++ x ++ "even" ;
|
||||||
|
Odd x = "is" ++ x ++ "odd" ;
|
||||||
|
Prime x = "is" ++ x ++ "prime" ;
|
||||||
|
Number n = n.s ;
|
||||||
|
|
||||||
|
Yes = "yes" ;
|
||||||
|
No = "no" ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
26
examples/tutorial/embedded/TransferDef.hs
Normal file
26
examples/tutorial/embedded/TransferDef.hs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
module TransferDef where
|
||||||
|
|
||||||
|
import PGF (Tree)
|
||||||
|
import Query -- generated from GF
|
||||||
|
|
||||||
|
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 [] = []
|
||||||
21
examples/tutorial/embedded/TransferLoop.hs
Normal file
21
examples/tutorial/embedded/TransferLoop.hs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import PGF
|
||||||
|
import TransferDef (transfer)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
gr <- readPGF "Query.pgf"
|
||||||
|
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) -> PGF -> String -> String
|
||||||
|
translate tr gr s = case parseAllLang gr (startCat gr) s of
|
||||||
|
(lg,t:_):_ -> linearize gr lg (tr t)
|
||||||
|
_ -> "NO PARSE"
|
||||||
5
examples/tutorial/resource-foods/FoodsSwe.gf
Normal file
5
examples/tutorial/resource-foods/FoodsSwe.gf
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
--# -path=.:../foods:present
|
||||||
|
|
||||||
|
concrete FoodsSwe of Foods = FoodsI with
|
||||||
|
(Syntax = SyntaxSwe),
|
||||||
|
(LexFoods = LexFoodsSwe) ;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
--# -path=.:../foods:present:prelude
|
--# -path=.:../foods:present:prelude
|
||||||
|
|
||||||
instance LexFoodsIta of LexFoods = open SyntaxIta, ParadigmsIta in {
|
instance LexFoodsIta of LexFoods = open SyntaxIta, ParadigmsIta, BeschIta in {
|
||||||
oper
|
oper
|
||||||
wine_N = mkN "vino" ;
|
wine_N = mkN "vino" ;
|
||||||
pizza_N = mkN "pizza" ;
|
pizza_N = mkN "pizza" ;
|
||||||
@@ -12,4 +12,9 @@ instance LexFoodsIta of LexFoods = open SyntaxIta, ParadigmsIta in {
|
|||||||
expensive_A = mkA "caro" ;
|
expensive_A = mkA "caro" ;
|
||||||
delicious_A = mkA "delizioso" ;
|
delicious_A = mkA "delizioso" ;
|
||||||
boring_A = mkA "noioso" ;
|
boring_A = mkA "noioso" ;
|
||||||
|
drink_V2 = mkV2 (verboV (bere_27 "bere")) ;
|
||||||
|
eat_V2 = mkV2 (mkV "mangiare") ;
|
||||||
|
pay_V2 = mkV2 (mkV "pagare") ;
|
||||||
|
gentleman_N = mkN "signore" ;
|
||||||
|
lady_N = mkN "signora" ;
|
||||||
}
|
}
|
||||||
|
|||||||
20
examples/tutorial/resource-foods/LexFoodsSwe.gf
Normal file
20
examples/tutorial/resource-foods/LexFoodsSwe.gf
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
instance LexFoodsSwe of LexFoods = open SyntaxSwe, ParadigmsSwe, IrregSwe in {
|
||||||
|
oper
|
||||||
|
wine_N = mkN "vin" "vinet" "viner" "vinerna" ;
|
||||||
|
pizza_N = mkN "pizza" ;
|
||||||
|
cheese_N = mkN "ost" ;
|
||||||
|
fish_N = mkN "fisk" ;
|
||||||
|
fresh_A = mkA "färsk" ;
|
||||||
|
warm_A = mkA "varm" ;
|
||||||
|
italian_A = mkA "italiensk" ;
|
||||||
|
expensive_A = mkA "dyr" ;
|
||||||
|
delicious_A = mkA "läcker" "läckert" "läckra" "läckrare" "läckrast" ;
|
||||||
|
boring_A = mkA "tråkig" ;
|
||||||
|
|
||||||
|
eat_V2 = mkV2 (mkV "äta" "åt" "ätit") ;
|
||||||
|
drink_V2 = mkV2 (mkV "dricka" "drack" "druckit") ;
|
||||||
|
pay_V2 = mkV2 "betala" ;
|
||||||
|
lady_N = mkN "dam" "damer" ;
|
||||||
|
gentleman_N = mkN "herr" ;
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user