From 2b5197d61d69f3843c6de31c9e6aa21243f66cde Mon Sep 17 00:00:00 2001 From: aarne Date: Wed, 4 Jul 2007 14:10:41 +0000 Subject: [PATCH] tutorial exercises; put libdir in place in GF/src --- doc/tutorial-next/gf-tutorial2.txt | 115 +++++++++++++++++++++-------- src/GF.hs | 4 +- src/GF/Infra/UseIO.hs | 7 +- 3 files changed, 91 insertions(+), 35 deletions(-) diff --git a/doc/tutorial-next/gf-tutorial2.txt b/doc/tutorial-next/gf-tutorial2.txt index 9323bad67..aa18dbfcd 100644 --- a/doc/tutorial-next/gf-tutorial2.txt +++ b/doc/tutorial-next/gf-tutorial2.txt @@ -30,7 +30,6 @@ Last update: %%date(%c) ==GF = Grammatical Framework== The term GF is used for different things: - - a **program** used for working with grammars - a **programming language** in which grammars can be written - a **theory** about grammars and languages @@ -39,7 +38,6 @@ The term GF is used for different things: This tutorial is primarily about the GF program and the GF programming language. It will guide you - - to use the GF program - to write GF grammars - to write programs in which GF grammars are used as components @@ -52,28 +50,26 @@ It will guide you A grammar is 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 +- **parsing**: to analyse the language +- **linearization**: to generate the language +- **translation**: to analyse one language and generate another A GF grammar can be seen as a declarative program from which these processing tasks can be automatically derived. In addition, many other tasks are readily available for GF grammars: - -- 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 -- teaching quizzes: train morphology and translation -- multilingual authoring: create a document in many languages simultaneously -- speech input: optimize a speech recognition system for your grammar +- **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 multiple linearizations +- **teaching quizzes**: train morphology and translation +- **multilingual authoring**: create a document in many languages simultaneously +- **speech input**: optimize a speech recognition system for your grammar A typical GF application is based on a **multilingual grammar** involving translation on a special domain. Existing applications of this idea include - - [Alfa: http://www.cs.chalmers.se/~hallgren/Alfa/Tutorial/GFplugin.html]: a natural-language interface to a proof editor (languages: English, French, Swedish) @@ -169,8 +165,7 @@ belongs to resource grammars, this tutorial will explain the programming concepts involved in morphology. This will moreover make it possible to grow the fragment covered by the food example. The tutorial will in fact build a miniature resource grammar in order -to illustrate the module structure of library-based application -grammar writing. +to give an introduction to linguistically oriented grammar writing. Thus it is by elaborating the initial ``food.cf`` example that the tutorial makes a guided tour through all concepts of GF. @@ -179,15 +174,17 @@ also the commands of the GF system are introduced as they are needed. To learn how to write GF grammars is not the only goal of -this tutorial. To learn the commands of the GF system means -that simple applications of grammars, such as translation and +this tutorial. We will also explain the most important +commands of the GF system. With these commands, +simple applications of grammars, such as translation and quiz systems, can be built simply by writing scripts for the system. More complicated applications, such as natural-language -interfaces and dialogue systems, also require programming in -some general-purpose language. We will briefly explain how +interfaces and dialogue systems, moreover require programming in +some general-purpose language. Thus will briefly explain how GF grammars are used as components of Haskell, Java, Javascript, -and Prolog grammars. The tutorial concludes with a couple of -case studies showing how such complete systems can be built. +and Prolog grammars. +%The tutorial concludes with a couple of +%case studies showing how such complete systems can be built. @@ -196,6 +193,7 @@ case studies showing how such complete systems can be built. The GF program is open-source free software, which you can download via the GF Homepage: + [``http://www.cs.chalmers.se/~aarne/GF`` http://www.cs.chalmers.se/~aarne/GF] There you can download @@ -204,14 +202,19 @@ There you can download - grammar libraries and examples -If you want to compile GF from source, you need Haskell and Java -compilers. But normally you don't have to compile, and you definitely +If you want to compile GF from source, you need a Haskell compiler. +For the interactive editor, you also need a Java compilers. +But normally you don't have to compile, and you definitely don't need to know Haskell or Java to use GF. -We are assuming the availability of a Unix shell. Mac OS X users -have it automatically, under the name "terminal". +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 program== + To start the GF program, assuming you have installed it, just type ``` % gf @@ -325,6 +328,29 @@ you imported. Try parsing something else, and you fail Unknown words: hello world ``` +**Exercise**. Extend the grammar ``food.cf`` by ten new food kinds and +qualities, and run the parser with new kinds of examples. + + +**Exercise**. Add a rule that enables questions of the form +//is this cheese Italian//. + + + +**Exercise**. Add the rule +``` + IsVery. S ::= Item "is" "very" Quality ; +``` +and see what happens when parsing ``this wine is very very Italian``. +You have just made the grammar **ambiguous**: it now assigns several +trees to some strings. + + +**Exercise**. Modify the grammar so that at most one ``Quality`` may +attach to a given ``Kind``. Thus //boring Italian fish// will no longer +be recognized. + + %--! @@ -422,11 +448,22 @@ You get quite a few trees but not all of them: only up to a given **depth** of trees. To see how you can get more, use the ``help = h`` command, ``` - help gt + > help gt ``` -**Quiz**. If the command ``gt`` generated all + +**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. You use the Unix **word count** command ``wc`` to count lines. +**Hint**. You can pipe the output of a GF command into a Unix command by +using the escape ``?``, as follows: +``` + > generate_trees | ? wc +``` + + + %--! @@ -450,7 +487,9 @@ This facility is good for test purposes: for instance, you may want to see if a grammar is **ambiguous**, i.e. contains strings that can be parsed in more than one way. -**Exercise**. Extend the grammar ``food.cf`` so that it produces ambiguous strings. +**Exercise**. Extend the grammar ``food.cf`` so that it produces ambiguous strings, +and try out the ambiguity test. + @@ -670,6 +709,10 @@ and of the type in subsequent ``fun`` judgements, ``` The order of judgements in a module is free. +**Exercise**. Extend the abstract syntax ``Food`` with ten new +kinds and qualities, and with questions of the form +//is this wine Italian//. + %--! @@ -703,6 +746,13 @@ apply as in ``abstract`` modules. } ``` +**Exercise**. Extend the concrete syntax ``FoodEng`` so that it +matches the abstract syntax defined in the exercise of the previous +section. What happens if the concrete syntax lacks some of the +new functions? + + + %--! ==Modules and files== @@ -1012,6 +1062,11 @@ are available: > help -printer > help help ``` +Another form of system commands are those usable in GF pipes. The escape symbol +is then ``?``. +``` + > generate_trees | ? wc +``` diff --git a/src/GF.hs b/src/GF.hs index 951bf4b52..30c9ab5a2 100644 --- a/src/GF.hs +++ b/src/GF.hs @@ -31,7 +31,7 @@ import GF.Shell.JGF import GF.System.Signal import GF.Text.UTF8 -import GF.Today (today,version) +import GF.Today (today,version,libdir) import GF.System.Arch import System (getArgs,system,getEnv) import Control.Monad (foldM,liftM) @@ -121,7 +121,7 @@ helpMsg = unlines [ welcomeMsgLib = do lib <- catch (getEnv "GF_LIB_PATH" >>= return . ("GF_LIB_PATH is set to" +++)) - (const (return "Warning: GF_LIB_PATH is not defined.")) + (const (return $ "GF_LIB_PATH is set to the default, " ++ libdir)) return $ welcomeMsg lib welcomeMsg lib = diff --git a/src/GF/Infra/UseIO.hs b/src/GF/Infra/UseIO.hs index 76563b5ad..dd8ad8d1a 100644 --- a/src/GF/Infra/UseIO.hs +++ b/src/GF/Infra/UseIO.hs @@ -17,6 +17,7 @@ module GF.Infra.UseIO where import GF.Data.Operations import GF.System.Arch (prCPU) import GF.Infra.Option +import GF.Today (libdir) import System.Directory import System.IO @@ -114,8 +115,8 @@ doesFileExistPath paths file = do -- | path in environment variable has lower priority extendPathEnv :: String -> String -> [FilePath] -> IO [FilePath] extendPathEnv lib var ps = do - b <- catch (getEnv lib) (const (return "")) -- e.g. GF_LIB_PATH - s <- catch (getEnv var) (const (return "")) -- e.g. GF_GRAMMAR_PATH + b <- catch (getEnv lib) (const (return libdir)) -- e.g. GF_LIB_PATH + s <- catch (getEnv var) (const (return "")) -- e.g. GF_GRAMMAR_PATH let fs = pFilePaths s let ss = ps ++ fs liftM concat $ mapM allSubdirs $ ss ++ [b ++ "/" ++ s | s <- ss] @@ -322,7 +323,7 @@ readFileLibraryIOE ini f = initPath = addInitFilePath ini f getLibPath :: IO String getLibPath = do { - lp <- getEnv gfLibraryPath; + lp <- catch (getEnv gfLibraryPath) (const (return libdir)) ; return (if isSep (last lp) then lp else lp ++ ['/']); } reportOn f = "File " ++ f ++ " not found."