diff --git a/doc/gf-tutorial.txt b/doc/gf-tutorial.txt index 7003dee1a..c556cbe64 100644 --- a/doc/gf-tutorial.txt +++ b/doc/gf-tutorial.txt @@ -4498,7 +4498,6 @@ the prefix is ``f`` instead of ``i``, and that ``fconst`` takes floating point literals as arguments. -%TODO: fix embedded grammars lesson #NEW @@ -4507,10 +4506,10 @@ point literals as arguments. #Lchapeight 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 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== 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: -- 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 +- PGF: a portable format for multilingual GF grammars +- a PGF interpreter written in the host language +- a library in the host language that enables calling the interpreter - 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". -A file can be produced in GF by the command -``` - > print_grammar | write_file FILE.pgf -``` -There is also a batch compiler, executable from the operative system shell: +This format is produced by the GF batch compiler ``gfc``, +executable from the operative system shell: ``` % 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 which final grammar products are distributed, because they 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. +%TODO convert the output to UTF8 + #NEW @@ -4694,27 +4688,14 @@ To reply in the //same// language as the question: #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 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=== +===Abstract syntax of the query system=== Input: abstract syntax judgements ``` +abstract Query = { + + flags startcat=Question ; + cat Answer ; Question ; Object ; @@ -4726,10 +4707,33 @@ Input: abstract syntax judgements Yes : 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 ``` -newtype GInt = GInt Integer +module Query where +import PGF data GAnswer = GYes @@ -4741,6 +4745,8 @@ data GQuestion = GPrime GObject | GOdd GObject | GEven GObject + +newtype GInt = GInt Integer ``` 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: - all GF names are in Haskell prefixed with ``G`` -- ``gf`` translates from Haskell to GF -- ``fg`` translates from GF to Haskell +- ``gf`` translates from Haskell objects to GF trees +- ``fg`` translates from GF trees to Haskell objects @@ -4805,7 +4811,7 @@ For the programmer, it is enougo to know: module TransferDef where import PGF (Tree) -import Math -- generated from GF +import Query -- generated from GF transfer :: Tree -> Tree transfer = gf . answer . fg @@ -4844,7 +4850,7 @@ import TransferDef (transfer) main :: IO () main = do - gr <- file2grammar "Math.pgf" + gr <- readPGF "Query.pgf" loop (translate transfer gr) loop :: (String -> String) -> IO () @@ -4855,7 +4861,7 @@ loop trans = do loop trans 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) _ -> "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: ``` all: - gfc --make -haskell MathEng.gf MathFre.gf + gfc --make --output-format=haskell QueryEng ghc --make -o ./math TransferLoop.hs strip math ``` @@ -4891,70 +4897,14 @@ Just to summarize, the source of the application consists of the following files TransferLoop.hs -- Haskell Main module ``` - #NEW -===Translets: embedded translators in Java=== - -**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] +TODO: web server applications #NEW -===Dialogue systems in Java=== - -**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. +TODO: JavaScript applications #NEW diff --git a/examples/tutorial/embedded/Makefile b/examples/tutorial/embedded/Makefile new file mode 100644 index 000000000..f1a61cb92 --- /dev/null +++ b/examples/tutorial/embedded/Makefile @@ -0,0 +1,4 @@ +all: + gfc --make --output-format=haskell QueryEng.gf + ghc --make -o ./math TransferLoop.hs + strip math diff --git a/examples/tutorial/embedded/Query.gf b/examples/tutorial/embedded/Query.gf new file mode 100644 index 000000000..b1ba23a87 --- /dev/null +++ b/examples/tutorial/embedded/Query.gf @@ -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 ; +} + diff --git a/examples/tutorial/embedded/QueryEng.gf b/examples/tutorial/embedded/QueryEng.gf new file mode 100644 index 000000000..a740056ee --- /dev/null +++ b/examples/tutorial/embedded/QueryEng.gf @@ -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" ; + +} + diff --git a/examples/tutorial/embedded/TransferDef.hs b/examples/tutorial/embedded/TransferDef.hs new file mode 100644 index 000000000..37d81c6dc --- /dev/null +++ b/examples/tutorial/embedded/TransferDef.hs @@ -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 [] = [] diff --git a/examples/tutorial/embedded/TransferLoop.hs b/examples/tutorial/embedded/TransferLoop.hs new file mode 100644 index 000000000..58498da11 --- /dev/null +++ b/examples/tutorial/embedded/TransferLoop.hs @@ -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" diff --git a/examples/tutorial/resource-foods/FoodsSwe.gf b/examples/tutorial/resource-foods/FoodsSwe.gf new file mode 100644 index 000000000..a77f924ad --- /dev/null +++ b/examples/tutorial/resource-foods/FoodsSwe.gf @@ -0,0 +1,5 @@ +--# -path=.:../foods:present + +concrete FoodsSwe of Foods = FoodsI with + (Syntax = SyntaxSwe), + (LexFoods = LexFoodsSwe) ; diff --git a/examples/tutorial/resource-foods/LexFoodsIta.gf b/examples/tutorial/resource-foods/LexFoodsIta.gf index be120a24e..2148953c3 100644 --- a/examples/tutorial/resource-foods/LexFoodsIta.gf +++ b/examples/tutorial/resource-foods/LexFoodsIta.gf @@ -1,6 +1,6 @@ --# -path=.:../foods:present:prelude -instance LexFoodsIta of LexFoods = open SyntaxIta, ParadigmsIta in { +instance LexFoodsIta of LexFoods = open SyntaxIta, ParadigmsIta, BeschIta in { oper wine_N = mkN "vino" ; pizza_N = mkN "pizza" ; @@ -12,4 +12,9 @@ instance LexFoodsIta of LexFoods = open SyntaxIta, ParadigmsIta in { expensive_A = mkA "caro" ; delicious_A = mkA "delizioso" ; 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" ; } diff --git a/examples/tutorial/resource-foods/LexFoodsSwe.gf b/examples/tutorial/resource-foods/LexFoodsSwe.gf new file mode 100644 index 000000000..12a2aaeee --- /dev/null +++ b/examples/tutorial/resource-foods/LexFoodsSwe.gf @@ -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" ; + +}